2010-09-30 17 views
11

के लिए डीएलएल खोज पथ को बदलना मैंने किसी भी संकेत की खोज की है कि मैं यह कैसे कर सकता हूं, लेकिन मुझे पता चला कि एसएक्सएस डीएलएल को स्थानीय एप्लिकेशन फ़ोल्डर में कैसे रीडायरेक्ट करना है। यहां मैं यह पूरा करना चाहता हूं: (सी ++) Application.exe एक डीएलएल, प्लगइन.डीएलएल (आश्रित परियोजना) से जुड़ा हुआ है। यह DLL एप्लिकेशन निर्देशिका के अंदर नहीं रखा गया है, लेकिन "प्लगइन्स" नामक उपफोल्डर में। चूंकि डीएलएल स्थिर रूप से जुड़ा हुआ है, तो एप्लिकेशन इसे एप्लिकेशन फ़ोल्डर से लोड करने का प्रयास करेगा।स्थैतिक लिंक किए गए डीएलएल

क्या कोई तरीका है कि मैं इस विशेष DLL के लिए खोज पथ कैसे बदल सकता हूं? या तो मैनिफ़ेस्ट या वीएस -2008 लिंकर कॉन्फ़िगरेशन के माध्यम से?

उत्तर

17

मेरा पहला विचार यह है कि, यदि आप स्थिर रूप से एक डीएलएल को जोड़ रहे हैं, तो यह एक प्लगइन नहीं है। बस EXE फ़ोल्डर में डीएल डालें और इसके साथ किया जाए। यह स्थिर रूप से लोड डीएलएल के लिए विंडोज़ द्वारा समर्थित तैनाती विन्यास है।

उस ने कहा, आप जो चाहते हैं उसे प्राप्त करने के तरीके हैं। लेकिन वे ज्यादातर बेवकूफ, या कोई अच्छे कारण के लिए जटिल हैं: आपके विकल्प हैं:

  • स्थिर लिंक न करें। प्लग इन सामग्री का उपयोग करने की LoadLibrary ("plugins/Plugin.dll") & GetProcAddress का प्रयोग करें।
  • सिस्टम पथ वातावरण चर करने के लिए "अपने प्लग-इन फ़ोल्डर के लिए पथ" जोड़ें।
  • प्लगइन्स कार्यक्षमता तक पहुँचने में देरी करने के देरी लोड तंत्र का उपयोग करें, एक प्रदान की पथ का उपयोग कर एक custom helper function कि dll (रों) लोड कर सकते हैं निर्धारित किया है।
  • (कि plugin.dll सूचीबद्ध करता है उस में एक .manifest फ़ाइल बनाने के द्वारा) मुड़ें
  • प्लगइन्स एक विधानसभा में फ़ोल्डर। अपने ऐप पर एक निर्भर असेंबली के रूप में "प्लगइन्स" जोड़ें। अब यह प्लगइन्स फ़ोल्डर में दिखेगा।
  • एक ठूंठ exe में अपने आवेदन और एक गतिशील लोड हिस्सा विभाजित करें। ठूंठ exe कॉल SetDllDirectory प्लगइन फ़ोल्डर को इंगित करने के लिए, तो LoadLibrary पूरा पथ "appstub.dll" करने के लिए गुजर कहते हैं।

एक फ़ोल्डर चालू करने के लिए एक या अधिक dll के साथ में एक "विधानसभा", बस फ़ोल्डरों name.manifest साथ फ़ोल्डर में एक फ़ाइल जोड़ें।

तो, plugins.manifest: -

<assembly manifestVersion="1.0"> 
    <assemblyIdentity type="Win32" name="Plugins" version="1.0.0.0" processorArchitecture="x86" /> 
    <file name="Plugin.dll"/> 
</assembly> 

यह एक बहुत अच्छा विचार है सुनिश्चित करने के लिए कि फ़ोल्डर और dll का नाम अलग है के रूप में यदि dll नाम विधानसभा नाम खिड़कियां है इसके एम्बेडेड को देख शुरू होता है असेंबली के बारे में जानकारी के लिए प्रकट फ़ाइल।

मान लिया जाये कि आप दृश्य स्टूडियो 7 या उसके बाद का उपयोग कर रहे, निम्नलिखित निर्देश एक ग/सीपीपी या करने के लिए जोड़ा।

#pragma comment(linker, "/manifestdependency:\"name='Plugins' "\ 
         "processorArchitecture='*' version='1.0.0.0' "\ 
         "type='win32'\"") 
+0

धन्यवाद - मैं अब GetProcAddress दृष्टिकोण के साथ गया हूं क्योंकि मुझे पता नहीं लगा कि मैनिफेस्ट को "फर्जी असेंबली" दृष्टिकोण कैसे काम करना है। सौभाग्य से, यह समग्र वास्तुकला के साथ अच्छी तरह से काम करता है। – Oliver

+1

आपको देरी लोडिंग के लिए 'SetDllDirectory' की आवश्यकता नहीं है; वहाँ '__pfnDliNotifyHook2' हुक है ताकि आप 'LoadLibrary ("। \\ plugins \\ PluginX.dll ") को सीधे कॉल कर सकें। '% पाथ%' विचार थोड़ा नाजुक है क्योंकि यह जांचने के लिए स्थानों की सूची पर कम है। – MSalters

+0

धन्यवाद। मैंने व्यक्तिगत रूप से देरी लोडिंग का व्यक्तिगत रूप से उपयोग नहीं किया है, इसलिए मैंने अभी माना है कि SetDllDirectory इसे ट्यून करने का तरीका होगा। –

5

विस्तार और एक "विधानसभा" उपनिर्देशिका की detailing Chris' proposal:


साइड नोट परियोजना में ज फ़ाइल फिर अपने आवेदन के बजाय स्थानीय निर्देशिका विधानसभा से DLLs लोड करने का प्रयास करेंगे :

  • AnswerDLL redirection using manifests
  • लिए: क्रिस भी अधिक जानकारी के के दो उत्कृष्ट लिखने अप है
  • A way to load DLL from central repository

    इस पर करने के लिए Answer भी बताते हैं कि कैसे आप आवेदन config फाइल में probing privatePath का लाभ उठाने के एक सबफ़ोल्डर के बाहर DLLs डाल करने के लिए कर सकते हैं।

    निजी विधानसभाओं आवेदन के निर्देशिका संरचना का एक फ़ोल्डर में स्थापित कर रहे हैं:


एमएस डॉक्स

यह वास्तव में एक "Private Assembly" और एमएस डॉक्स कहा जाता है कि यह इस तरह की व्याख्या। आम तौर पर, यह फ़ोल्डर है जिसमें एप्लिकेशन की निष्पादन योग्य फ़ाइल है। निजी विधानसभाओं रूप में एक ही नाम का एक फ़ोल्डर में में आवेदन के रूप में एक ही फ़ोल्डर, तैनात किया जा सकता है विधानसभा, या विधानसभा के रूप में एक ही नाम के साथ एक भाषा विशिष्ट सबफ़ोल्डर में।

उदाहरण (...) के लिए

Appdir\Microsoft.Tools.Pop\Microsoft.Tools.Pop.MANIFEST: प्रकट एक सबफ़ोल्डर विधानसभा का नाम होने में एक अलग फाइल के रूप में तैनात किया गया है।

(...)

निजी विधानसभाओं किसी भी स्थापना विधि है कि इस तरह xcopy आदेश के रूप में इस फ़ोल्डर में विधानसभा की फाइल कॉपी कर सकते हैं, द्वारा स्थापित किया जा सकता।

उदाहरण

आप आप आप इस कार्यक्रम फ़ोल्डर C:\Test\Program\app.exe में भरोसेमंद पुराने निष्पादन कर रहे हैं मिला है और आप चाहते हैं - at Load-Time - अपने DLL फ़ाइल साथ खिलवाड़ के बिना C:\Test\Program\plugins\tool1.dll, Plugins सबफ़ोल्डर से लोड यानी PATH या कोई अन्य सामान।

  • साथ app.exe संकलित करें:

    आप की जरूरत है

    #pragma comment(linker, "/manifestdependency:\"name='Plugins' version='1.0.0.0' type='win32'\"") 
    // name, type and version seems to be the minimum info to get away with 
    

    नोट: संकलन/इस में लिंक करने के बजाय एक बाहरी प्रकट (app.exe.manifest) का उपयोग करने के लिए आवश्यक है पर मेरी टेस्ट सिस्टम, मुझे अभी तक क्यों पता नहीं चला।(* क)

    क्या भी काम करता है लेकिन embedding है/प्रकट mt उपकरण के साथ निष्पादन में नीचे सूचीबद्ध फ़ाइल विलय, बजाय लिंकर pragma के साथ की। (Configuration > Manifest Tool > Additional Manifest Files)

  • डाल plugins सबफ़ोल्डर

  • परिचय tool1.dll प्लगइन्स सबफ़ोल्डर में एक plugins.manifest फ़ाइल जोड़ने के लिए, यानी C:\Test\Program\plugins\plugins.manifest और है कि एक इस तरह दिखता है:

प्लगइन्स। मेनिफेस्ट:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
    <assemblyIdentity 
          type="win32" 
          name="Plugins" 
          version="1.0.0.0" 
      /> 
    <file name="tool1.dll"/> 
</assembly> 

यही है। App.exe प्रारंभ करना लोड-टाइम पर सबफ़ोल्डर में स्वचालित रूप से डीएलएल पायेगा।


(* एक): इस मैनिफ़ेस्ट फ़ाइल विलय से काम करता है, लेकिन आप उपयोग नहीं कर सकते एकमात्र बाहरी मैनिफ़ेस्ट फ़ाइल के रूप में है, और मुझे लगता है कि यह क्योंकि यह अन्य सभी प्रकट की जानकारी निर्माण सिस्टम पहले से ही में स्थानों याद आ रही है आपका निष्पादन योग्य!

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
    <dependency> 
     <dependentAssembly> 
      <!-- Note: type: The value must be win32 and all in lower case. Required. --> 
      <!-- Note: version: The value must be win32 and all in lower case. Required. --> 
      <assemblyIdentity 
            type="win32" 
            name="plugins" 
            version="1.0.0.0" 
      /> 
     </dependentAssembly> 
    </dependency> 
</assembly> 
+0

numpy विकी @ https://github.com/numpy/numpy/wiki/windows-dll-notes भी इस –

+0

का एक अच्छा लिखना भी है बाहरी बाहरी फ़ाइल का उपयोग केवल मुझे लगता है कि अगर कोई एम्बेडेड मेनिफेस्ट फ़ाइल नहीं है। वीएस कंपाइलर अब डिफ़ॉल्ट रूप से प्रकट होता है इसलिए मैनिफ़ेस्ट की रनटाइम लोडिंग केवल तभी संभव है जब आप इसे पहले हटा दें। –

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