c++ सी++: अलग डायरेक्टरी से मैलफाईस्ट और गतिशील रूप से डीएलएल लोड हो रहे हैं




dll manifest (3)

मैं क्या हासिल करने की कोशिश कर रहा हूं, इसकी लंबी कहानी

मैं एक प्रोग्राम पर काम कर रहा हूं जो गतिशील रूप से DLLs को प्लगइन्स के रूप में लोड करता है। मैं माइक्रोसॉफ्ट विज़ुअल सी ++ 2008 का उपयोग कर कार्यक्रम को संकलित कर रहा हूं। फिर भी, मान लें कि किसी भी विजुअल सी ++ संस्करण के साथ क्यूटी कार्य समर्थित होना चाहिए। प्रोग्राम निर्देशिका लेआउट निम्नलिखित है:

| plugins/
|   plugin1.dll
|   plugin2.dll
| QtCore4.dll
| QtGui4.dll
| program.exe

program.exe सभी plugins DLL फ़ाइलों को पता चलता है, उन पर LoadLibrary () करता है और यह वास्तव में एक प्लगइन है या नहीं, यह पता लगाने के लिए एक निश्चित हस्ताक्षर फ़ंक्शन कॉल करता है। यह उन कंप्यूटरों पर काफी अच्छी तरह से काम करता है, जो कि एमएसवीसी 9 090 के लिए vcredist हैं। स्वाभाविक रूप से, सभी कंप्यूटरों पर प्रोग्राम काम करने के लिए मुझे इसे एमएसवीसी * .डीएल फाइलों के साथ और उपयुक्त मैनिफ़ेस्ट फ़ाइल के साथ पुनर्वितरित करना होगा। क्यूटी डीएलएल को भी चलाने के लिए पुनः चलाने की आवश्यकता होती है।

अब, मैंने स्वचालित रूप से उपयुक्त रेडलिस्ट डीएलएल की प्रतिलिपि बनाने और चयनित विजुअल स्टूडियो संस्करण के आधार पर प्रकट होने के लिए सेंमीक सेट अप किया है। सादगी के लिए हमें यह मानते रहें कि मैं एमएसवीसी 9 0 9 के साथ काम कर रहा हूं। जब redist प्रोग्राम निर्देशिका में कॉपी हो जाता है लेआउट इस तरह दिखता है:

| plugins/
|   plugin1.dll
|   plugin2.dll
| QtCore4.dll
| QtGui4.dll
| msvcm90.dll
| msvcp90.dll
| msvcr90.dll
| Microsoft.VC90.CRT.manifest (I'm also aware that this file is bugged in VS2008)
| program.exe

मैनिफेस्ट फ़ाइल में बग के बारे में: http://www.cmake.org/pipermail/cmake/2008- सितंबर 0223822.html

समस्या

इस लेआउट वाला प्रोग्राम अब उन कंप्यूटरों पर काम करता है, जो कि रेडिस्ट स्थापित नहीं है, लेकिन प्लग-इन लोड नहीं हो रहे हैं। प्लग इन को लोड करने के लिए मुझे निम्न में से एक करना है:

  1. मैनिफेस्ट फ़ाइल पर plugins/ निर्देशिका में कॉपी करें मेनिफेस्ट फ़ाइल से एमएसवीसी *। Dll फ़ाइलों के सभी संदर्भ निकाल दें यह काम करता है लेकिन यह अच्छा नहीं है क्योंकि मुझे इस्तेमाल किए गए MSVC के संस्करण के आधार पर संपादित मैनिफ़ेस्ट फ़ाइलों के विभिन्न संस्करणों का समर्थन करना होगा। इसके अलावा, मुझे नहीं पता है कि यह 2008 के अलावा दृश्य स्टूडियो से नहीं टूट जाएगा।
  2. संपूर्ण रीडिस्ट को plugins/ निर्देशिका में कॉपी करें यह मैनिफ़ेस्ट फ़ाइल में किसी भी संशोधन की आवश्यकता नहीं है, लेकिन अब program.exe । Exe बेवक़ूफ़ एमएसवीसी * .डीएलएल फ़ाइलों को लोड करने की कोशिश करता है जो वे प्लगइन्स हैं। स्वाभाविक रूप से, यह असीम रूप से विफल रहता है इसलिए कोई बड़ा नुकसान नहीं किया गया है। अन्य दोष यह है कि प्रोग्राम पैकेज का आकार 1 MB से अधिक हो जाता है। ये दोनों मुद्दे कुछ ऐसा है जो मैं साथ रह सकता हूं, यद्यपि।
  3. / MT स्विच के साथ प्लग इन संकलित करें संक्षिप्त परीक्षण से पता चला है कि यह वास्तव में काम करता है लेकिन मुझे यकीन नहीं है कि भविष्य में अगर यह दोनों क्यूटी और program.exeprogram.exe / एमडी हैं, तो यह कुछ भी नहीं तोड़ देगा।

प्रश्न)

सबसे अच्छा समाधान क्या है? सही समाधान क्या है? अगर एक से अधिक सही समाधान है तो सबसे अच्छा अभ्यास क्या है? क्या मैं पहली बार ऐसा करने की कोशिश कर रहा हूं?

अपडेट 1 (18 नवंबर 2012)

जबकि सवाल का उत्तर नहीं दिया गया है, मैंने उस मार्ग के लिए जाने का फैसला किया जो कम से कम सिरदर्द का कारण बनता है। अब तक मैं समाधान नंबर 1 का उपयोग कर रहा हूं और मैंने इसके साथ रहना तय किया है। अगर CMake पता लगाता है कि उपयोगकर्ता 2008 से भिन्न एमएसवीसी संस्करण का उपयोग कर रहा है तो यह एक चेतावनी संदेश दिखाएगा कि स्वचालित पैकेजिंग पूरी तरह से समर्थित नहीं है।


आप अधिष्ठापन प्रक्रिया में CreateHardLink () फ़ंक्शन के साथ वीसी डीएलएस के लिए हार्डलिंक बना सकते हैं। विधि (1) के साथ जो आपने वर्णित किया है, वीसीआरटी डीएलएस की अलग-अलग प्रतियां के साथ कुछ समस्याएं हो सकती हैं। हार्डलिंक्स या सेटडेल डायरेक्टरी () सबसे अच्छा समाधान लगता है

एमएसवीसीआरटी के लिए एक एकल प्रक्रिया स्थिर और गतिशील लिंक में मिश्रण न करें - यह हमेशा आपको समस्याएं देता है!


आप "LoadLibrary" को पूर्ण फ़ाइल पथ प्रदान कर सकते हैं, ताकि आप अपने प्लग इन अपने पथ के साथ लोड कर सकें। मैंने इस सटीक लेआउट का उपयोग एक ही पुस्तकालय के कई संस्करणों को वर्तमान स्टूडियो 2005 में मौजूदा डीएलएल के उपनिर्देशिका से लोड करने के लिए किया है।

आपको सबसे पहले मौजूदा डीएलएल का वर्तमान पथ प्राप्त करना होगा:

static LPSTR strDLLPath1 = new TCHAR[_MAX_PATH+1];
::GetModuleFileName((HINSTANCE)&__ImageBase, strDLLPath1, _MAX_PATH);

यद्यपि आपका प्रोग्राम। Exe पहले से ही इन प्लगइन फ़ाइलों को खोज रहा है, तो मुझे लगता होगा कि आपके पास पहले से उनके पूर्ण पथ तक पहुंच है।


यदि आपका लक्ष्य ओएस में _WIN32_WINNT> = 0x0502 है तो आप फ़ंक्शन का उपयोग कर सकते हैं

SetDllDirectory()

प्लग इन लोड करने से पहले

मुख्य प्रोग्राम फ़ोल्डर को पथ डालें

कॉल ओवरराइड सिस्टम लोड ऑर्डर:

  1. जिस निर्देशिका से एप्लिकेशन लोड किया गया है
  2. डायरेक्टरी को पथ से SetDllDirectory () कॉल में निर्दिष्ट किया गया है

इसलिए, आप एप्लिकेशन को शुरू होने के बाद फ़ंक्शन को कॉल कर सकते हैं। यह सभी मामलों में सुरक्षित है सौभाग्य!







vcredist