एम्बेडेड संसाधन के रूप में किसी अन्य के अंदर एक डीएल एम्बेड करना और फिर इसे मेरे कोड से कॉल करना

मुझे एक ऐसी स्थिति मिली है जहां मेरे पास एक डीएलएल है जो मैं बना रहा हूं जो किसी अन्य तृतीय पक्ष डीएलएल का उपयोग करता है, लेकिन यदि मैं संभव हो तो दोनों को एक साथ रखने के बजाय मैं अपने डीएलएल में तीसरे पक्ष के डीएलएल का निर्माण करने में सक्षम होना पसंद करूंगा।

यह सी # और .NET 3.5 है।

जिस तरह से मैं ऐसा करना चाहता हूं वह तीसरे पक्ष के डीएलएल को एक एम्बेडेड संसाधन के रूप में संग्रहीत करना है जिसे मैं पहले डीएलएल के निष्पादन के दौरान उचित स्थान पर रखता हूं।

जिस तरह से मैंने मूल रूप से ऐसा करने की योजना बनाई थी, वह कोड कोड द्वारा तीसरे पक्ष के डीएलएल को System.Reflection.Assembly.GetExecutingAssembly() द्वारा निर्दिष्ट स्थान में डालने के लिए है। स्थान.ToString() अंतिम /nameOfMyAssembly.dll से कम करें। मैं इस स्थान में तीसरे पक्ष .DLL को सफलतापूर्वक सहेज सकता हूं (जो समाप्त होता है

सी: \ दस्तावेज़ और सेटिंग्स \ myUserName \ स्थानीय सेटिंग्स \ अनुप्रयोग   डेटा \ असेंबली \ dl3 \ KXPPAX6Y.ZCY \ A1MZ1499.1TR \ e0115d44 \ 91bb86eb_fe18c901

), लेकिन जब मैं अपने डीएलएल की आवश्यकता वाले मेरे कोड के हिस्से में जाता हूं, तो उसे यह नहीं मिल रहा है।

क्या किसी के पास कोई विचार है कि मुझे अलग-अलग काम करने की क्या ज़रूरत है?

0

6 उत्तर

एक बार संसाधन के रूप में तृतीय-पक्ष असेंबली को एम्बेड करने के बाद, AppDomain.AssemblyResolve एप्लिकेशन स्टार्ट-अप के दौरान वर्तमान डोमेन की घटना। जब भी सीएलआर की फ़्यूज़न उप-प्रणाली असफलता (नीतियों) के अनुसार असेंबली का पता लगाने में विफल रहता है तो यह घटना आग लगती है। AppDomain.AssemblyResolve के लिए ईवेंट हैंडलर में assembly.GetManifestResourceStream और अपनी सामग्री को बाइट सरणी के रूप में संबंधित assembly.Load अधिभार। नीचे यह है कि सी # में ऐसा कोई कार्यान्वयन कैसा दिख सकता है:

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    var resName = args.Name + ".dll";    
    var thisAssembly = Assembly.GetExecutingAssembly();    
    using (var input = thisAssembly.GetManifestResourceStream(resName))
    {
        return input != null 
             ? Assembly.Load(StreamToBytes(input))
             : null;
    }
};

जहां StreamToBytes को परिभाषित किया जा सकता है:

static byte[] StreamToBytes(Stream input) 
{
    var capacity = input.CanSeek ? (int) input.Length : 0;
    using (var output = new MemoryStream(capacity))
    {
        int readLength;
        var buffer = new byte[4096];

        do
        {
            readLength = input.Read(buffer, 0, buffer.Length);
            output.Write(buffer, 0, readLength);
        }
        while (readLength != 0);

        return output.ToArray();
    }
}

आखिरकार, जैसा कि कुछ पहले से ही उल्लेख कर चुके हैं, ILMerge विचार करने का एक और विकल्प हो सकता है, यद्यपि कुछ हद तक अधिक शामिल है।

0
जोड़ा
GetManifestResourceStream? असेंबली * .Properties.Resources नामस्थान के तहत एक दृढ़ता से टाइप की गई संपत्ति होगी।
जोड़ा लेखक Will, स्रोत
पोस्टिंग के बाद मुझे पता चला कि @dgvid ने प्रतिक्रिया समय में मुझे हराया। : पी
जोड़ा लेखक Atif Aziz, स्रोत
वह चिकना है, अच्छी तरह से किया।
जोड़ा लेखक jcollum, स्रोत
मैंने इस कोड को वास्तव में वही करने के लिए बहुत सफलतापूर्वक इस्तेमाल किया जो मैं चाहता था। मेरे द्वारा तय किए गए कुछ मामूली वाक्यविन्यास चूक के लिए मेरी पोस्ट देखें (इसे संपादित करने के लिए पर्याप्त प्रतिनिधि नहीं है))।
जोड़ा लेखक Lawrence Johnston, स्रोत
रुको, इसलिए इसे अभी भी exe के "नियंत्रण" की आवश्यकता है, रिचटर का विचार (जो कि इस जवाब को" चोरी "लगता है) सुझाव होना चाहिए? उस लिंक पर 28 जुलाई 2010 3:14 अपराह्न से शुरू होने वाली टिप्पणी के लिए खोजें मैं जवाब में "एप्लिकेशन स्टार्ट-अप के दौरान" पर क्लिक कर रहा हूं - यह तब काम नहीं करता है जब यह काम नहीं करता है आप केवल एक डीएल वितरित कर रहे हैं और exe तक पहुंच नहीं है?
जोड़ा लेखक ruffin, स्रोत
उन लोगों के लिए जिन्होंने पहले विधानसभा वर्ग का उपयोग नहीं किया है, आपको एक सिस्टम का उपयोग करना होगा। प्रतिबिंब; कथन। मुझे यह समझने में थोड़ा सा लगा कि किस कथन का उपयोग गायब था, इसलिए शायद यह किसी की मदद करेगा।
जोड़ा लेखक Keith, स्रोत

डिस्क पर असेंबली लिखने के बजाय आप असेंबली करने की कोशिश कर सकते हैं। लोड (बाइट [] rawAssembly) जहां आप एम्बेडेड संसाधन से rawAssembly बनाते हैं।

0
जोड़ा

अंत में मैंने लगभग कुछ ही मामूली परिवर्तनों और कुछ चूक को छोड़कर, रबूफ ने सुझाव दिया (और डीजीवीआईडी ​​के समान सुझाव दिया)। मैंने इस विधि को चुना क्योंकि यह पहली जगह के लिए सबसे नज़दीक था और किसी तीसरे पक्ष के निष्पादन योग्य और इस तरह के उपयोग की आवश्यकता नहीं थी। यह बहुत अच्छा काम करता है!

यह मेरा कोड समाप्त हो गया है जैसा दिख रहा है:

संपादित करें: मैंने इस फ़ंक्शन को किसी अन्य असेंबली में स्थानांतरित करने का निर्णय लिया है, इसलिए मैं इसे कई फ़ाइलों में पुन: उपयोग कर सकता हूं (मैं बस विधानसभा में जाता हूं। GetExecutingAssembly ())।

यह अद्यतन संस्करण है जो आपको एम्बेडेड डीएलएस के साथ असेंबली में पास करने की अनुमति देता है।

एम्बेडेड रिसोर्सप्रैक्स एम्बेडेड संसाधन के लिए स्ट्रिंग पथ है, यह आमतौर पर असेंबली का नाम होगा जिसके बाद संसाधन युक्त किसी भी फ़ोल्डर संरचना (जैसे "MyComapny.MyProduct.MyAssembly.Resources" है यदि डीएलएल परियोजना में संसाधन नामक फ़ोल्डर में है )। यह भी मानता है कि डीएलएल में .dll.resource एक्सटेंशन है।

   public static void EnableDynamicLoadingForDlls(Assembly assemblyToLoadFrom, string embeddedResourcePrefix) {
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {//had to add =>
            try {
                string resName = embeddedResourcePrefix + "." + args.Name.Split(',')[0] + ".dll.resource";
                using (Stream input = assemblyToLoadFrom.GetManifestResourceStream(resName)) {
                    return input != null
                         ? Assembly.Load(StreamToBytes(input))
                         : null;
                }
            } catch (Exception ex) {
                _log.Error("Error dynamically loading dll: " + args.Name, ex);
                return null;
            }
        };//Had to add colon
    }

    private static byte[] StreamToBytes(Stream input) {
        int capacity = input.CanSeek ? (int)input.Length : 0;
        using (MemoryStream output = new MemoryStream(capacity)) {
            int readLength;
            byte[] buffer = new byte[4096];

            do {
                readLength = input.Read(buffer, 0, buffer.Length);//had to change to buffer.Length
                output.Write(buffer, 0, readLength);
            }
            while (readLength != 0);

            return output.ToArray();
        }
    }
0
जोड़ा
अपना अंतिम कोड पोस्ट करने के लिए धन्यवाद, मैं उस जगह का उपयोग कर समाप्त कर सकता हूं!
जोड़ा लेखक Rob Ringham, स्रोत

मैंने सफलतापूर्वक ऐसा किया है जो आप वर्णन कर रहे हैं, लेकिन क्योंकि तीसरे पक्ष के डीएलएल भी एक .NET असेंबली है, मैं इसे डिस्क पर कभी नहीं लिखता, मैं बस इसे स्मृति से लोड करता हूं।

मुझे एक बाइट सरणी के रूप में एम्बेडेड संसाधन असेंबली मिलती है:

        Assembly resAssembly = Assembly.LoadFile(assemblyPathName);

        byte[] assemblyData;
        using (Stream stream = resAssembly.GetManifestResourceStream(resourceName))
        {
            assemblyData = ReadBytesFromStream(stream);
            stream.Close();
        }

फिर मैं विधानसभा के साथ डेटा लोड करता हूं। लोड ()।

अंत में, मैं AppDomain.CurrentDomain.Assembly पर एक हैंडलर जोड़ता हूं जब लोड लोडर इसे देखता है तो मेरी लोडेड असेंबली को वापस करने के लिए पुन: प्रयास करें।

अतिरिक्त विवरण के लिए .NET फ़्यूज़न कार्यशाला देखें।

0
जोड़ा

There's a tool called IlMerge that can accomplish this: http://research.microsoft.com/~mbarnett/ILMerge.aspx

फिर आप निम्न के जैसा एक बिल्ड इवेंट बना सकते हैं।

सेट पथ = "सी: \ प्रोग्राम फ़ाइलें \ माइक्रोसॉफ्ट \ ILMerge"

ilmerge /out:$(ProjectDir)\Deploy\LevelEditor.exe $ (ProjectDir) \ bin \ Release \ release.exe $ (ProjectDir) \ bin \ Release \ InteractLib.dll $ (ProjectDir) \ bin \ Release \ SpriteLib.dll $ (ProjectDir) \ बिन \ रिलीज \ LevelLibrary.dll

0
जोड़ा

You can achieve this remarkably easily using Netz, a .net NET Executables Compressor & Packer.

0
जोड़ा