تضمين dll واحد داخل آخر كمورد مضمن ثم الاتصال به من التعليمة البرمجية الخاصة بي

لقد حصلت على وضع حيث لدي DLL أنا إنشاء يستخدم DLL طرف ثالث آخر ، لكنني أفضل أن يكون قادراً على إنشاء DLL طرف ثالث في DLL الخاص بي بدلاً من الحاجة إلى الاحتفاظ بها معاً إذا أمكن.

هذا مع C# و. NET 3.5.

الطريقة أرغب في القيام بذلك عن طريق تخزين DLL طرف ثالث كمورد مضمن الذي ثم ضع في المكان المناسب أثناء تنفيذ DLL الأول.

الطريقة التي خططت أصلا للقيام بذلك هي كتابة التعليمات البرمجية لوضع DLL الطرف الثالث في الموقع المحدد بواسطة System.Reflection.Assembly.GetExecutingAssembly (). Location.ToString() ناقص آخر /nameOfMyAssembly.dll . يمكنني حفظ الطرف الثالث .DLL بنجاح في هذا الموقع (الذي ينتهي به الأمر

C: \ Documents and Settings \ myUserName \ Local Settings \ Application   Data \ assembly \ dl3 \ KXPPAX6Y.ZCY \ A1MZ1499.1TR \ e0115d44 \ 91bb86eb_fe18c901

) ، ولكن عندما أحصل على جزء من الرمز الخاص بي يتطلب هذا DLL ، فإنه لا يمكن العثور عليه.

هل لدى أي شخص فكرة عما أحتاج إلى القيام به بشكل مختلف؟

0
وأضاف تحرير
الآراء: 1

6 إجابة

بمجرد تضمين تجميع الجهة الخارجية كمورد ، أضف التعليمات البرمجية للاشتراك في AppDomain.AssemblyResolve حدث في النطاق الحالي أثناء بدء التطبيق. ينطلق هذا الحدث عندما يفشل النظام الفرعي Fusion لـ CLR في تحديد موقع تجميع وفقًا للسياقات (السياسات) السارية. في معالج الحدث الخاص بـ AppDomain.AssemblyResolve ، قم بتحميل المصدر باستخدام Assembly.GetManifestResourceStream وإطعام محتواه بصفته صفيف بايت في Assembly.Load الزائد. فيما يلي كيفية ظهور مثل هذا التنفيذ في C #:

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();
    }
}

أخيرًا ، وكما ذكر عدد قليل من المستخدمين ، قد يكون

0
وأضاف
GetManifestResourceStream؟ سيكون التجميع خاصية مكتوبة بشدة تحت مساحة الاسم * .Properties.Resources.
وأضاف المؤلف Will, مصدر
أدركت بعد نشر ذلك @ dggid يضربني في وقت الاستجابة. : P
وأضاف المؤلف Atif Aziz, مصدر
هذا هو البقعة ، أحسنت.
وأضاف المؤلف jcollum, مصدر
لقد استخدمت هذا الرمز بنجاح كبير للقيام بما أردت. انظر منصبي لاثنين من سهو الجملة طفيفة أنا ثابت (لا يكفي rep لتحرير هذا واحد ؛)).
وأضاف المؤلف Lawrence Johnston, مصدر
انتظر ، لذلك هذا لا يزال يتطلب "التحكم" من exe ، مثل فكرة ريختر (التي يبدو أنها" سرقت "هذه الإجابة) تشير إلى أنه يجب أن يحدث؟ ابحث عن التعليق بدءًا من 28 يوليو 2010 3:14 مساءًا على هذا الرابط أنا أقوم بالتسوية على "أثناء بدء التطبيق" في الإجابة أعلاه - وهذا لا يعمل عندما كنت فقط توزيع دلل وليس لديك الوصول إلى إكس؟
وأضاف المؤلف ruffin, مصدر
لأولئك الذين لم يستخدموا فئة الجمعية من قبل ، تحتاج إلى الحصول على باستخدام System.Reflection ؛ . استغرق الأمر بعض الشيء لمعرفة ما إذا كان استخدام العبارة مفقودًا ، لذلك ربما يساعد هذا الشخص.
وأضاف المؤلف Keith, مصدر

بدلاً من كتابة التجميع على القرص ، يمكنك محاولة القيام بـ Assembly.Load (byte [] rawAssembly) حيث تقوم بإنشاء rawAssembly من المورد المضمن.

0
وأضاف

في النهاية لقد فعلت ذلك بالضبط بالضبط الطريقة المقترحة raboof (وعلى غرار ما اقترح dgvid) ، إلا مع بعض التغييرات الطفيفة وبعض الثابتة السهو. لقد اخترت هذه الطريقة لأنها كانت الأقرب إلى ما كنت أبحث عنه في المقام الأول ولم أكن بحاجة إلى استخدام أي برامج تنفيذية تابعة لجهات خارجية. إنها تعمل بشكل رائع!

هذا ما انتهى به الأمر برمجي:

تحرير: قررت نقل هذه الوظيفة إلى تجميع آخر حتى أتمكن من إعادة استخدامه في ملفات متعددة (أنا فقط تمر في Assembly.GetExecutingAssembly ()).

هذا هو الإصدار المحدث الذي يسمح لك بالمرور في التجميع مع dlls المضمنة.

embeddedResourcePrefix هو مسار السلسلة إلى المورد المضمن ، وعادة ما يكون اسم التجميع متبوعًا بأي بنية مجلد تحتوي على المورد (على سبيل المثال "MyComapny.MyProduct.MyAssembly.Resources" إذا كان dll في مجلد يسمى الموارد في المشروع ). يفترض أيضًا أن dll له ملحق .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, مصدر

لقد نجحت في تنفيذ ما تصفه ، ولكن لأن DLL التابع لجهة خارجية هو أيضًا تجميع .NET ، لا أقوم أبدًا بكتابته إلى القرص ، أقوم فقط بتحميله من الذاكرة.

أحصل على تجميع الموارد المضمنة كصفيف بايت مثل:

        Assembly resAssembly = Assembly.LoadFile(assemblyPathName);

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

ثم أقوم بتحميل البيانات مع Assembly.Load ().

وأخيراً ، أقوم بإضافة معالج إلى AppDomain.CurrentDomain.AssemblyResolve لإرجاع التجميع المحمل الخاص بي عندما يبدو من نوع المحمل.

راجع .NET Fusion Workshop للحصول على تفاصيل إضافية.

0
وأضاف

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

بعد ذلك ، يمكنك إنشاء حدث بناء مماثل لما يلي.

Set Path = "C: \ Program Files \ Microsoft \ 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
وأضاف