2012-11-04 15 views
8

मैं क्या हासिल करना

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

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

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

अब, मैंने चयनित रेडिस्ट डीएलएल पर स्वचालित रूप से प्रतिलिपि बनाने के लिए सेमेक सेट किया है और चयनित विजुअल स्टूडियो संस्करण के आधार पर प्रकट किया है। सादगी के लिए मान लीजिए कि मैं MSVC90 के साथ काम कर रहा हूं। 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-September/023822.html

समस्या

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

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

सवाल (रों)

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

अद्यतन 1 (18 नवम्बर 2012)

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

+1

आप अपने ऐप के लिए और आपके प्लगइन के लिए रन-टाइम क्यों स्थिर रूप से लिंक नहीं करते हैं? –

+0

क्यूटी पहले से ही vcredist की आवश्यकता है, इसलिए मुझे इसे किसी भी तरह शामिल करना होगा। इसके अलावा संसाधन आवंटन के साथ समस्याएं हैं जब संसाधन एक स्थाई रूप से जुड़ी इकाई में आवंटित किया जाता है और फिर किसी अन्य में जारी किया जाता है - यह असुरक्षित है और प्रोग्राम क्रैश हो सकता है। मुझे नहीं पता कि क्यूटी/एमडी अगर क्यूटी के साथ कैसे व्यवहार करेगा। – ZalewaPL

+1

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

उत्तर

0

अपने लक्ष्य ओएस है _WIN32_WINNT> = 0x0502 से आप समारोह

SetDllDirectory() 

उपयोग कर सकते हैं इससे पहले कि आप प्लग-इन लोड हो रहा है।

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

कॉल ओवरराइड प्रणाली लोड आदेश:

  1. निर्देशिका है जहाँ से आवेदन लोड।
  2. SetDllDirectory() कॉल में पथ द्वारा निर्दिष्ट निर्देशिका।

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

+0

काम नहीं लग रहा है। – ZalewaPL

0

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

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

1

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

आप पहली बार उपयोग करते हुए वर्तमान dll की वर्तमान पथ प्राप्त करने के लिए की जरूरत है:

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

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

संबंधित मुद्दे