[c#] تضمين DLLs في الملف التنفيذي المترجمة


Answers

إذا كانت تُدار بالفعل التجميعات ، يمكنك استخدام ILMerge . بالنسبة إلى ملفات DLL الأصلية ، سيكون لديك المزيد من العمل للقيام به.

راجع أيضًا: كيف يمكن دمج windows C ++ في واجهة تطبيق C #؟

Question

أنت تعرف ، أنا لم أر إجابة جيدة لهذا في أي مكان. هل من الممكن تضمين DLL موجود مسبقا في C # قابل للتنفيذ المترجمة (بحيث يكون لديك ملف واحد فقط لتوزيع)؟ إذا كان ذلك ممكنًا ، كيف يمكن للمرء أن يفعل ذلك؟

عادة ، أنا بارد مع مجرد ترك DLLs في الخارج ووجود برنامج الإعداد التعامل مع كل شيء ، ولكن كان هناك اثنين من الناس في العمل الذين سألوني هذا وأنا بصراحة لا أعرف.




إلى جانب ILMerge ، إذا كنت لا تريد أن تهتم بمفاتيح سطر الأوامر ، فإنني أوصي ILMerge-Gui . إنه مشروع مفتوح المصدر ، جيد حقًا!




بشكل عام ، ستحتاج إلى شكل من أشكال أداة إنشاء النشر لأداء دمج التجميع كما تصفه. هناك أداة مجانية تسمى Eazfuscator (eazfuscator.blogspot.com/) والتي تم تصميمها للشفرة bytecode التي تتعامل أيضًا مع دمج التجميع. يمكنك إضافة هذا إلى سطر الأوامر postbuilding مع Visual Studio لدمج التجميعات الخاصة بك ، ولكن قد تختلف المسافة المقطوعة الخاصة بك بسبب المشكلات التي ستظهر في أي سيناريوهات دمج تجميع غير متساوية.

يمكنك أيضًا التحقق لمعرفة ما إذا كان الإنشاء يؤدي إلى عدم القدرة على العمل NANT لديه القدرة على دمج التجميعات بعد البناء ، لكنني لست على دراية كافية مع NANT بنفسي لأقول ما إذا كانت الوظيفة مضمنة أم لا.

هناك أيضًا العديد من العديد من ملحقات Visual Studio التي ستنفذ دمج التجميع كجزء من إنشاء التطبيق.

بدلاً من ذلك ، إذا لم تكن بحاجة إلى القيام بذلك تلقائيًا ، فهناك عدد من الأدوات مثل ILMerge التي ستقوم بدمج تجميعات net في ملف واحد.

أكبر مشكلة واجهتها مع دمج التجميعات هي إذا كانت تستخدم أي مساحات أسماء مشابهة. أو أسوأ من ذلك ، مرجع إصدارات مختلفة من نفس دلل (كانت مشاكلي بشكل عام مع ملفات DLL NUnit).




تحقق BoxedApp

يمكن تضمين DLL في أي تطبيق. مكتوبة في C # أيضا ، بالطبع :)

آمل أن يساعد.




يمكنني استخدام المحول البرمجي csc.exe استدعاؤه من برنامج نصي .vbs.

في البرنامج النصي xyz.cs الخاص بك ، أضف الأسطر التالية بعد التوجيهات (المثال الخاص بـ Renci SSH):

using System;
using Renci;//FOR THE SSH
using System.Net;//FOR THE ADDRESS TRANSLATION
using System.Reflection;//FOR THE Assembly

//+ref>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+res>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+ico>"C:\Program Files (x86)\Microsoft CAPICOM 2.1.0.2 SDK\Samples\c_sharp\xmldsig\resources\Traffic.ico"

سيتم اختيار العلامات ref و res و ico بواسطة البرنامج النصي .vbs أدناه لتشكيل أمر csc.

ثم قم بإضافة المتصل محلل التجميع في Main:

public static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    .

... وأضف المحلل نفسه في مكان ما في الصف:

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        String resourceName = new AssemblyName(args.Name).Name + ".dll";

        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
        {
            Byte[] assemblyData = new Byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return Assembly.Load(assemblyData);
        }

    }

اسمي البرنامج النصي VBS لتتناسب مع اسم الملف .cs (على سبيل المثال ssh.vbs يبحث عن ssh.cs) ؛ هذا يجعل تشغيل البرنامج النصي أكثر سهولة كثيرًا ، ولكن إذا لم تكن أحمقًا مثلي ، فيمكن لبرنامج نصي عام التقاط ملف .cs الهدف من السحب والإفلات:

    Dim name_,oShell,fso
    Set oShell = CreateObject("Shell.Application")
    Set fso = CreateObject("Scripting.fileSystemObject")

    'TAKE THE VBS SCRIPT NAME AS THE TARGET FILE NAME
    '################################################
    name_ = Split(wscript.ScriptName, ".")(0)

    'GET THE EXTERNAL DLL's AND ICON NAMES FROM THE .CS FILE
    '#######################################################
    Const OPEN_FILE_FOR_READING = 1
    Set objInputFile = fso.OpenTextFile(name_ & ".cs", 1)

    'READ EVERYTHING INTO AN ARRAY
    '#############################
    inputData = Split(objInputFile.ReadAll, vbNewline)

    For each strData In inputData

        if left(strData,7)="//+ref>" then 
            csc_references = csc_references & " /reference:" &         trim(replace(strData,"//+ref>","")) & " "
        end if

        if left(strData,7)="//+res>" then 
            csc_resources = csc_resources & " /resource:" & trim(replace(strData,"//+res>","")) & " "
        end if

        if left(strData,7)="//+ico>" then 
            csc_icon = " /win32icon:" & trim(replace(strData,"//+ico>","")) & " "
        end if
    Next

    objInputFile.Close


    'COMPILE THE FILE
    '################
    oShell.ShellExecute "c:\windows\microsoft.net\framework\v3.5\csc.exe", "/warn:1 /target:exe " & csc_references & csc_resources & csc_icon & " " & name_ & ".cs", "", "runas", 2


    WScript.Quit(0)



نعم ، من الممكن دمج الملفات التنفيذية لـ .NET مع المكتبات. هناك العديد من الأدوات المتاحة لإنجاز المهمة:

  • ILMerge هي أداة مساعدة يمكن استخدامها لدمج مجموعات .NET متعددة في تجميع واحد.
  • أحادية mkbundle ، حزم إكس وجميع الجمعيات مع libmono في حزمة ثنائية واحدة.
  • IL-Repack هو جهاز FLOSS مبدئي في ILMerge ، مع بعض الميزات الإضافية.

بالإضافة إلى ذلك ، يمكن دمج هذا مع Mono Linker ، الذي يقوم بإزالة التعليمات البرمجية غير المستخدمة وبالتالي يجعل التجميع الناتج أصغر.

هناك احتمال آخر وهو استخدام .NETZ ، والذي لا يسمح فقط بضغط مجموعة ، بل يمكنه أيضًا تجميع dlls مباشرةً في exe. الاختلاف في الحلول المذكورة أعلاه هو أن .NETZ لا يدمجها ، فإنها تبقى تجميعات منفصلة ولكنها معبأة في حزمة واحدة.

.NETZ هي أداة مفتوحة المصدر تقوم بضغط وحزم ملفات Microsoft .NET Framework القابلة للتنفيذ (EXE، DLL) من أجل جعلها أصغر.




منتج آخر يمكن أن يتعامل مع هذا الأنيق هو SmartAssembly ، في SmartAssembly.com . سيقوم هذا المنتج ، بالإضافة إلى دمج كافة التبعيات في DLL واحد (اختياريًا) تشويش التعليمات البرمجية الخاصة بك وإزالة بيانات التعريف الإضافية لتقليل حجم الملف الناتج ، ويمكن أيضًا تحسين IL لزيادة أداء وقت التشغيل. هناك أيضًا نوع من ميزة الاستثناء / معالجة الاستثناءات العالمية التي تضيفها إلى برنامجك (إذا رغبت في ذلك) ، ولم أكن أفهم الوقت ، ولكن قد يكون مفيدًا. وأعتقد أنه يحتوي أيضًا على واجهة برمجة تطبيقات سطر الأوامر حتى تتمكن من جعلها جزءًا من عملية الإنشاء.




أنصحك بالاطلاع على الأداة المساعدة NETZ ، والتي تقوم أيضًا بضغط التجميع مع نظام من اختيارك:

http://madebits.com/netz/help.php#single




مقتطفات من جيفري ريختر جيد جدا. باختصار ، قم بإضافة المكتبة كموارد مضمنة وإضافة استدعاء قبل أي شيء آخر. هنا نسخة من الشفرة (موجودة في تعليقات صفحته) التي أضعها في بداية الطريقة الرئيسية لتطبيق وحدة التحكم (فقط تأكد من أن أي مكالمات تستخدم المكتبة تكون بطريقة مختلفة عن Main).

AppDomain.CurrentDomain.AssemblyResolve += (sender, bargs) =>
        {
            String dllName = new AssemblyName(bargs.Name).Name + ".dll";
            var assem = Assembly.GetExecutingAssembly();
            String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName));
            if (resourceName == null) return null; // Not found, maybe another handler will find it
            using (var stream = assem.GetManifestResourceStream(resourceName))
            {
                Byte[] assemblyData = new Byte[stream.Length];
                stream.Read(assemblyData, 0, assemblyData.Length);
                return Assembly.Load(assemblyData);
            }
        };



Links