संकलित निष्पादन योग्य में DLL एम्बेड करना


618

क्या किसी पूर्व-मौजूदा DLL को संकलित C # निष्पादन योग्य में एम्बेड करना संभव है (ताकि आपके पास वितरित करने के लिए केवल एक फ़ाइल हो)? यदि यह संभव है, तो कोई इसे कैसे करेगा?

आम तौर पर, मैं सिर्फ DLL को बाहर छोड़ने और सेटअप प्रोग्राम को संभालने के साथ ही सबकुछ शांत रहता हूं, लेकिन काम के दौरान कुछ लोग ऐसे भी हैं जिन्होंने मुझसे यह पूछा है और मैं ईमानदारी से नहीं जानता।


मैं आपको .NETZ उपयोगिता की जांच करने की सलाह दूंगा, जो आपकी पसंद की एक योजना के साथ असेंबली को संपीड़ित करता है: http://madebits.com/netz/help.php#single
नाथन बलोच

2
यह संभव है, लेकिन आप बड़े निष्पादन योग्य के साथ समाप्त हो जाएंगे (Base64 का उपयोग आपके dll को एन्कोड करने के लिए किया जाएगा)।
पावेल डिडा 13

ILMerge के अलावा , यदि आप कमांड लाइन स्विच से परेशान नहीं करना चाहते हैं, तो मैं वास्तव में ILMerge-Gui की सलाह देता हूं । यह एक ओपन सोर्स प्रोजेक्ट है, वास्तव में अच्छा है!
tyron

2
@ PawełDyda: आप कच्चे बाइनरी डेटा को पीई इमेज ( RCDATA देखें ) में एम्बेड कर सकते हैं । कोई परिवर्तन आवश्यक (या अनुशंसित)।
IInspectable

जवाबों:


761

मैं Costura.Fody का उपयोग करने के लिए अत्यधिक सलाह देता हूं - आपकी विधानसभा में संसाधनों को एम्बेड करने का सबसे अच्छा और आसान तरीका। यह NuGet पैकेज के रूप में उपलब्ध है।

Install-Package Costura.Fody

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

Install-CleanReferencesTarget

आप यह भी निर्दिष्ट करने में सक्षम होंगे कि क्या पीडीबी को शामिल करना, कुछ विधानसभाओं को बाहर करना, या मक्खी पर विधानसभाओं को निकालना। जहाँ तक मुझे पता है, अनवांटेड असेंबली भी समर्थित हैं।

अपडेट करें

वर्तमान में, कुछ लोग DNX के लिए समर्थन जोड़ने की कोशिश कर रहे हैं ।

अपडेट २

नवीनतम फ़ॉडी संस्करण के लिए, आपको MSBuild 16 (इसलिए Visual Studio 2019) की आवश्यकता होगी। Fody संस्करण 4.2.1 MSBuild 15. करेगा (संदर्भ: Fody केवल MSBuild 16 और इसके बाद के संस्करण पर समर्थित है। वर्तमान संस्करण 15 )


79
इस भयानक सुझाव के लिए धन्यवाद। पैकेज स्थापित करें और आप कर रहे हैं। यह डिफ़ॉल्ट रूप से असेंबलियों को भी संपीड़ित करता है।
डेनियल

9
'मुझे भी' होने से नफरत है, लेकिन मुझे भी - इससे मुझे बहुत सिरदर्द हुआ! सिफ़ारिश के लिए शुक्रिया! इसने मुझे वह सब कुछ पैकेज करने में सक्षम किया जो मुझे एक ही exe में पुनर्वितरित करने की आवश्यकता है और यह अब मूल exe से छोटा है और dlls संयुक्त थे ... मैं केवल कुछ दिनों के लिए इसका उपयोग कर रहा हूं, इसलिए मैं यह नहीं कह सकता कि मैं ' मैं इसे अपने पेस के माध्यम से डाल रहा हूं, लेकिन कुछ भी खराब पॉपिंग को रोककर, मैं इसे अपने टूलबॉक्स में एक नियमित टूल बन सकता हूं। यह सिर्फ काम करता है!
मैटजेल

19
यह बढ़ीया है। लेकिन एक नुकसान है: विंडोज पर उत्पन्न असेंबली मोनो लिनक्स के साथ अब बाइनरी संगत नहीं है। इसका मतलब है, आप सीधे लिनक्स मोनो पर असेंबली को तैनात नहीं कर सकते।
टायलर लॉन्ग

7
ये बहुत प्यारी है! यदि आप vs2018 का उपयोग कर रहे हैं, तो अपने प्रोजेक्ट के रूट पर स्थित FodyWeavers.xml फ़ाइल को न भूलें।
एलन डीप

4
अंतिम टिप्पणी के पूरक के रूप में: अपनी परियोजना के लिए निम्न सामग्री के साथ FodyWeavers.xml जोड़ें: -? Xml संस्करण = "1.0" एन्कोडिंग = "utf-8"?> <बुनकरों VerifyAssembly = "सही"> <कोस्टुरा /> </ बुनकर>
HHenn

88

विजुअल स्टूडियो में अपनी परियोजना को राइट-क्लिक करें, प्रोजेक्ट गुण चुनें -> संसाधन -> संसाधन जोड़ें -> मौजूदा फ़ाइल जोड़ें ... और नीचे दिए गए कोड को अपने App.xaml.cs या समकक्ष में शामिल करें।

public App()
{
    AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");

    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);
}

यहाँ मेरा मूल ब्लॉग पोस्ट है: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/


6
आपके पास यह व्यवहार बॉक्स से बाहर हो सकता है। मेरा जवाब देखें stackoverflow.com/a/20306095/568266
Matthias

4
AshRowe से अपने ब्लॉग पर एक उपयोगी उपयोगी टिप्पणी को नोट करने के लिए भी महत्वपूर्ण है: यदि आपके पास एक कस्टम विषय स्थापित है, तो यह PresentationFramework.Theme असेंबली को हल करने का प्रयास करेगा जो क्रैश और जलता है! AshRowe के सुझाव के अनुसार, आप बस यह देख सकते हैं कि dllName में PresentationFramework शामिल है जैसे: यदि (dllName.ToLower ()। इसमें शामिल हैं ("प्रेजेंटफ़्रेमवर्क")) null;
यशभारम्

4
इस पर दो टिप्पणियाँ। एक: आपको जांच करनी चाहिए कि bytesक्या अशक्त है, और यदि ऐसा है, तो अशक्त लौटें। यह संभव है कि dll संसाधनों में नहीं है, आखिरकार। दो: यह केवल तभी काम करता है जब उस वर्ग के पास उस विधानसभा की किसी भी चीज़ के लिए "उपयोग" न हो। कमांड लाइन टूल के लिए, मुझे अपने वास्तविक प्रोग्राम कोड को एक नई फ़ाइल में स्थानांतरित करना होगा, और एक छोटा सा नया मुख्य प्रोग्राम बनाना होगा जो बस ऐसा करता है और फिर पुराने वर्ग में मूल मुख्य कॉल करता है।
Nyerguds

2
इस दृष्टिकोण का उल्टा तरीका यह है कि यह वांछित कार्यक्षमता को प्राप्त करने के लिए किसी भी बाहरी देयता को स्थापित करने में भरोसा नहीं करता है। इस दृष्टिकोण का नकारात्मक पक्ष यह है कि यह केवल तभी उपयोगी है जब यह प्रबंधित dlls के लिए आता है - इंटरॉप dlls (कम से कम जहाँ तक मेरा परीक्षण चला जाता है) असेंबली को हल न करें और भले ही उन्होंने असेंबली की हो। .dll>) सड़क के नीचे वांछनीय प्रभाव को प्राप्त नहीं करता है। stackoverflow.com/questions/13113131/… इस मामले पर सिर्फ मेरा 2 सी
एक्सडीएस

3
बस अगर कोई मेरे मुद्दे में भागता है: यदि .dllनाम में कोई हाइफ़न (यानी twenty-two.dll) है, तो वे भी एक अंडरस्कोर (यानी twenty_two.dll) के साथ बदल दिए जाएंगे । आप इस कोड को इस प्रकार बदल सकते हैं:dllName = dllName.Replace(".", "_").Replace("-", "_");
मीका वर्टाल

87

यदि वे वास्तव में विधानसभाओं का प्रबंधन कर रहे हैं, तो आप ILMerge का उपयोग कर सकते हैं । देशी DLL के लिए, आपके पास करने के लिए थोड़ा और काम होगा।

इसे भी देखें: C ++ विंडोज़ को C # एप्लिकेशन exe में कैसे मिलाया जा सकता है?


मुझे मूल निवासी डीएलएल मर्ज में दिलचस्पी है, क्या कोई सामग्री है?
बैयान हुआंग


@BaiyanHuang को github.com/boxedapp/bxilmerge पर देखें, देशी Dll के लिए "ILMerge" बनाने का विचार है।
आर्टेम रेज़िन

मेरे जैसे वीबी नेट डेवलपर्स C++लिंक पर उस से डरते नहीं हैं । ILMerge भी VB NET के लिए बहुत आसानी से काम करता है। यहाँ देखें https://github.com/dotnet/ILMerge । धन्यवाद @ शोग 9
इवान फेरर विला

26

हाँ, पुस्तकालयों के साथ .NET निष्पादनों को मर्ज करना संभव है। काम पूरा करने के लिए कई उपकरण उपलब्ध हैं:

  • ILMerge एक उपयोगिता है जिसका उपयोग कई .NET असेंबली को एक असेंबली में मर्ज करने के लिए किया जा सकता है।
  • मोनो mkbundle , एक exe और सभी असेंबलियों को एक सिंगल बाइनरी पैकेज में libmono के साथ पैकेज करता है।
  • IL-Repack ILMerge में एक FLOSS परिवर्तनशील है, जिसमें कुछ अतिरिक्त विशेषताएं हैं।

इसके अलावा इसे मोनो लिंकर के साथ जोड़ा जा सकता है , जो अप्रयुक्त कोड को हटाता है और इसके परिणामस्वरूप परिणामी विधानसभा को छोटा बनाता है।

एक अन्य संभावना .NETZ का उपयोग करना है , जो न केवल एक असेंबली को संपीड़ित करने की अनुमति देता है, बल्कि dll को सीधे exe में भी पैक कर सकता है। उपर्युक्त समाधानों के लिए अंतर यह है कि .NETZ उन्हें विलय नहीं करता है, वे अलग-अलग विधानसभाओं में रहते हैं लेकिन एक पैकेज में पैक किए जाते हैं।

.NETZ एक खुला स्रोत उपकरण है जो Microsoft .NET फ्रेमवर्क निष्पादन योग्य (EXE, DLL) फ़ाइलों को छोटा करने के लिए उन्हें संकुचित और पैक करता है।


NETZ लगता है
Rbjz

वाह - मुझे लगा कि मुझे आखिरकार मिल गया है, तो मैंने यह टिप्पणी पढ़ी। यह पूरी तरह से चला गया लगता है। क्या कोई कांटे हैं?
Mafii

खैर, यह सिर्फ GitHub में चला गया और यह अब वेबसाइट पर जुड़ा नहीं है ... इसलिए "पूरी तरह से चला गया" एक ओवरस्टेटमेंट है। सबसे अधिक संभावना है कि यह अब समर्थित नहीं है, लेकिन यह अभी भी है। मैंने लिंक अपडेट किया।
बॉबी

20

ILMerge असेंबली को एक ही असेंबली में जोड़ सकता है बशर्ते असेंबली में केवल प्रबंधित कोड हो। आप कमांडलाइन ऐप का उपयोग कर सकते हैं, या exe और प्रोग्रामेटिक रूप से मर्ज करने के लिए संदर्भ जोड़ सकते हैं। एक GUI संस्करण के लिए Eazfuscator है , और .Netz भी दोनों ही मुफ्त हैं। पेड ऐप्स में BoxedApp और SmartAssembly शामिल हैं

यदि आपको असम्बद्ध कोड के साथ असेंबलियों को मर्ज करना है, तो मैं सुझाव दूंगा कि SmartAssembly । मुझे कभी भी SmartAssembly के साथ लेकिन अन्य सभी के साथ हिचकी नहीं थी । यहां, यह आवश्यक निर्भरता को आपके मुख्य exe के लिए संसाधनों के रूप में एम्बेड कर सकता है।

यदि आप अपने संसाधनों को dll एम्बेड करके और फिर AppDomain की असेंबली पर निर्भर होकर असेंबली प्रबंधित या मिश्रित मोड में है, तो आपको मैन्युअल रूप से चिंता करने की आवश्यकता नहीं है ResolveHandler। यह सबसे खराब स्थिति है, यानी असम्बद्ध कोड के साथ असेंबलियों को अपनाने से एक बंद समाधान है।

static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string assemblyName = new AssemblyName(args.Name).Name;
        if (assemblyName.EndsWith(".resources"))
            return null;

        string dllName = assemblyName + ".dll";
        string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);

        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
        {
            byte[] data = new byte[stream.Length];
            s.Read(data, 0, data.Length);

            //or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);

            File.WriteAllBytes(dllFullPath, data);
        }

        return Assembly.LoadFrom(dllFullPath);
    };
}

यहां कुंजी एक फाइल को बाइट्स लिखने और उसके स्थान से लोड करने के लिए है। चिकन और अंडे की समस्या से बचने के लिए, आपको यह सुनिश्चित करना होगा कि आप असेंबली एक्सेस करने से पहले हैंडलर की घोषणा करें और लोडिंग (असेंबली रिजॉल्विंग) भाग के अंदर आप असेंबली मेंबर्स (या असेंबली से जुड़ी किसी भी चीज को तुरंत एक्सेस न करें) को एक्सेस न करें। यह भी ध्यान रखें GetMyApplicationSpecificPath()कि कोई भी टेंपरेरी डायरेक्टरी नहीं है क्योंकि टेंप फाइल्स को अन्य प्रोग्राम या खुद से मिटाने का प्रयास किया जा सकता है (ऐसा नहीं है कि यह डिलीट हो जाएगा जबकि आपका प्रोग्राम डीएल एक्सेस कर रहा है, लेकिन कम से कम इसका उपद्रव अच्छा है।) स्थान)। यह भी ध्यान दें कि आपको हर बार बाइट्स लिखनी होती हैं, आप लोकेशन से लोड नहीं कर सकते हैं 'क्योंकि dll पहले से ही रहता है।

प्रबंधित dlls के लिए, आपको बाइट्स लिखने की आवश्यकता नहीं है, लेकिन सीधे dll के स्थान से लोड करें, या बस बाइट्स पढ़ें और मेमोरी से असेंबली लोड करें। इस तरह या तो:

    using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
    {
        byte[] data = new byte[stream.Length];
        s.Read(data, 0, data.Length);
        return Assembly.Load(data);
    }

    //or just

    return Assembly.LoadFrom(dllFullPath); //if location is known.

यदि असेंबली पूरी तरह से अप्रबंधित है, तो आप इस लिंक या इस तरह के dll को लोड करने के लिए देख सकते हैं ।


ध्यान दें कि संसाधन के "बिल्ड एक्शन" को "एंबेडेड संसाधन" पर सेट करने की आवश्यकता है।
मावामार्टन

@ मवमार्टन जरूरी नहीं है। यदि यह प्रोजेक्ट के Resources.resx में पहले से जोड़ा जाता है, तो आपको ऐसा करने की आवश्यकता नहीं है।
Nyerguds

2
EAZfuscator अब वाणिज्यिक है।
टेलीमैट

16

जेफरी रिक्टर द्वारा अंश बहुत अच्छा है। संक्षेप में, लाइब्रेरी के एम्बेडेड संसाधनों को जोड़ें और किसी अन्य चीज़ से पहले कॉलबैक जोड़ें। यहां कोड का एक संस्करण है (उसके पृष्ठ की टिप्पणियों में पाया गया) जो मैंने एक कंसोल ऐप के लिए मुख्य विधि की शुरुआत में रखा है (बस यह सुनिश्चित करें कि कोई भी कॉल जो लाइब्रेरी के मुख्य के लिए एक अलग विधि का उपयोग कर रहे हैं)।

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

1
इसे थोड़ा बदल दिया, काम किया, tnx दोस्त!
सीन एड-मैन

प्रोजेक्ट libz.codeplex.com इस प्रक्रिया का उपयोग करता है, लेकिन यह कुछ अन्य चीजें भी करेगा जैसे कि आपके लिए ईवेंट हैंडलर को प्रबंधित करना और कुछ विशेष कोड " प्रबंधित एक्स्टेंसिबिलिटी फ्रेमवर्क कैटलॉग " को तोड़ने के लिए नहीं है (जो स्वयं इस प्रक्रिया को तोड़ देगा)
स्कॉट चैंबरलेन

एक दम बढ़िया!! साभार @ सेतेव
अहमर अफ़ज़ल

14

ऊपर @ बॉबी के asnwer पर विस्तार करने के लिए । जब आप निर्माण करते हैं तो आप सभी फ़ाइलों को एक ही असेंबली में स्वचालित रूप से पैकेज करने के लिए IL-Repack का उपयोग करने के लिए अपने .csproj को संपादित कर सकते हैं ।

  1. के साथ nuget ILRepack.MSBuild.Task पैकेज स्थापित करें Install-Package ILRepack.MSBuild.Task
  2. अपने .csproj के AfterBuild अनुभाग को संपादित करें

यहाँ एक सरल नमूना है जो आपके प्रोजेक्ट आउटपुट में ExampleAssemblyToMerge.dll को मर्ज करता है।

<!-- ILRepack -->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

   <ItemGroup>
    <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
    <InputAssemblies Include="$(OutputPath)\ExampleAssemblyToMerge.dll" />
   </ItemGroup>

   <ILRepack 
    Parallel="true"
    Internalize="true"
    InputAssemblies="@(InputAssemblies)"
    TargetKind="Exe"
    OutputFile="$(OutputPath)\$(AssemblyName).exe"
   />
</Target>

1
IL-Repack का सिंटैक्स बदल गया है, README.md की जाँच करें जो लिंक्ड गितुब रेपो ( github.com/peters/ILRepack.MSBuild.Task ) पर है। यह तरीका एकमात्र था जिसने मेरे लिए काम किया और मैं उन सभी डीएल से मेल खाने के लिए वाइल्डकार्ड का उपयोग करने में सक्षम था जिसे मैं शामिल करना चाहता था।
सीबास77 Sea

8

आप DLL को एम्बेडेड संसाधनों के रूप में जोड़ सकते हैं, और फिर आपका प्रोग्राम उन्हें स्टार्टअप पर एप्लिकेशन डायरेक्टरी में अनपैक कर सकता है (यह देखने के बाद कि क्या वे पहले से ही हैं, यह देखने के लिए जाँच करें)।

सेटअप फ़ाइलें बनाना आसान है, हालांकि, मुझे नहीं लगता कि यह इसके लायक होगा।

EDIT: यह तकनीक .NET असेंबली के साथ आसान होगी। गैर- .NET DLL के साथ यह एक बहुत अधिक काम होगा (आपको यह पता लगाना होगा कि फ़ाइलों को कहां अनपैक करना है और उन्हें पंजीकृत करना है और इसलिए)।


यहाँ आपके पास एक बढ़िया लेख है जो बताता है कि यह कैसे करना है: codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource
bluish

8

एक अन्य उत्पाद जो इस सुरुचिपूर्ण तरीके से संभाल सकता है वह है SmartAssembly, SmartAssembly.com पर । यह उत्पाद सभी निर्भरता को एक DLL में विलय करने के अलावा, (वैकल्पिक रूप से) आपके कोड को बाधित करेगा, परिणामस्वरूप फ़ाइल आकार को कम करने के लिए अतिरिक्त मेटा-डेटा को हटा देगा, और रनटाइम प्रदर्शन को बढ़ाने के लिए वास्तव में IL को भी अनुकूलित कर सकता है।

कुछ प्रकार की वैश्विक अपवाद हैंडलिंग / रिपोर्टिंग सुविधा भी है जो आपके सॉफ़्टवेयर में जुड़ती है (यदि वांछित है) जो उपयोगी हो सकती है। मेरा मानना ​​है कि इसमें कमांड-लाइन एपीआई भी है ताकि आप इसे अपनी निर्माण प्रक्रिया का हिस्सा बना सकें।


7

न तो ILMerge दृष्टिकोण और न ही लार्स होल्म जेन्सेन की असेंबली को नियंत्रित करना। ईवेंट एक प्लगइन होस्ट के लिए काम करेगा। निष्पादनीय एच असेंबली पी को गतिशील रूप से लोड करता है और इसे एक अलग असेंबली में परिभाषित इंटरफ़ेस आईपी ​​के माध्यम से एक्सेस करता है । IP को H में एम्बेड करने के लिए Lars के कोड में थोड़ा संशोधन करना होगा:

Dictionary<string, Assembly> loaded = new Dictionary<string,Assembly>();
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{   Assembly resAssembly;
    string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
    dllName = dllName.Replace(".", "_");
    if ( !loaded.ContainsKey( dllName ) )
    {   if (dllName.EndsWith("_resources")) return null;
        System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
        byte[] bytes = (byte[])rm.GetObject(dllName);
        resAssembly = System.Reflection.Assembly.Load(bytes);
        loaded.Add(dllName, resAssembly);
    }
    else
    {   resAssembly = loaded[dllName];  }
    return resAssembly;
};  

एक ही विधानसभा को हल करने के लिए बार-बार किए गए प्रयासों को संभालने की चाल और एक नया उदाहरण बनाने के बजाय मौजूदा एक को वापस करना।

संपादित करें: ऐसा न हो कि यह .NET के क्रमांकन को बिगाड़ दे, सुनिश्चित करें कि सभी असेंबली के लिए अशक्त वापस आ जाएँ, जो कि आपके अंदर एम्बेडेड नहीं हैं, जिससे मानक व्यवहार के लिए डिफ़ॉल्ट है। आप इन पुस्तकालयों की एक सूची प्राप्त कर सकते हैं:

static HashSet<string> IncludedAssemblies = new HashSet<string>();
string[] resources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
for(int i = 0; i < resources.Length; i++)
{   IncludedAssemblies.Add(resources[i]);  }

और यदि विधानसभा पास नहीं होती है तो बस वापस आ जाएं IncludedAssemblies


टिप्पणी के बजाय उत्तर के रूप में पोस्ट करने के लिए क्षमा करें। मुझे दूसरों के उत्तरों पर टिप्पणी करने का अधिकार नहीं है।
Ant_222

5

.NET Core 3.0 मूल रूप से एकल .exe के संकलन का समर्थन करता है

आपकी परियोजना फ़ाइल (.csproj) में निम्नलिखित संपत्ति के उपयोग से यह सुविधा सक्षम है:

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>

यह बिना किसी बाहरी उपकरण के किया जाता है।

अधिक जानकारी के लिए इस प्रश्न के लिए मेरा उत्तर देखें।


3

यह सरल लग सकता है, लेकिन WinRar फ़ाइलों का एक गुच्छा एक आत्म-निष्पादनीय निष्पादन को संपीड़ित करने का विकल्प देता है।
इसके बहुत सारे विन्यास विकल्प हैं: अंतिम आइकन, दिए गए पथ पर फ़ाइलों को निकालने, निष्कर्षण के बाद निष्पादित करने के लिए फ़ाइल, कस्टम लोगो / निष्कर्षण के दौरान दिखाए गए पॉपअप के लिए ग्रंथ, कोई पॉपअप विंडो बिल्कुल नहीं, लाइसेंस समझौता पाठ, आदि
कुछ मामलों में उपयोगी हो सकते हैं। ।


विंडोज के पास एक ऐसा ही टूल है जिसका नाम है iexpress। यहाँ एक ट्यूटोरियल है
इवान फेरर विला

2

मैं एक .vbs स्क्रिप्ट से बुलाया csc.exe संकलक का उपयोग करता हूं।

अपनी xyz.cs स्क्रिप्ट में, निर्देशों के बाद निम्नलिखित पंक्तियाँ जोड़ें (मेरा उदाहरण रेंकी एसएसएच के लिए है):

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"

Csc कमांड बनाने के लिए .vbs स्क्रिप्ट के द्वारा Ref, Res और ico टैग्स को उठाया जाएगा।

फिर मुख्य में असेंबली रिज़ॉल्वर कॉलर जोड़ें:

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

... और वर्ग में कहीं और ही रिज़ॉल्वर जोड़ें:

    स्थिर विधानसभा CurrentDomain_AssemblyResolve (ऑब्जेक्ट प्रेषक, ResolveEventArgs args)
    {
        स्ट्रिंग संसाधननाम = नया असेंबलीनाम (args.Name) .Name + ".dll";

        उपयोग (var stream = Assembly.GetExecutingAssembly ()। GetManifestResourceStream (रिसोर्सनाम)
        {
            बाइट [] असेंबलीडाटा = नई बाइट [स्ट्रीम.लिफ्ट];
            स्ट्रीम। रीडेड (असेंबलीडैटा, 0, असेम्बलीडैटा.लिफ्ट);
            असेंबली वापस करें। लोड (असेंबलीडेटा);
        }

    }

मैं .bs फ़ाइल नाम (जैसे ssh.vbs ssh.cs के लिए दिखता है) से मेल करने के लिए vbs स्क्रिप्ट का नाम देता हूं; इससे स्क्रिप्ट को कई बार चलाना बहुत आसान हो जाता है, लेकिन अगर आप मेरी तरह बेवकूफ नहीं हैं, तो एक सामान्य स्क्रिप्ट टारगेट को ड्रैग-एंड-ड्रॉप से ​​उठा सकती है।

    मंद नाम_, ओशेल, धड़
    सेट oShell = CreateObject ("Shell.Application")
    Fso सेट करें = CreateObject ("Scripting.fileSystemObject")

    'VBS SCRIPT का नाम TARGET FILE NAME के ​​रूप में रखें
    '################################################
    name_ = विभाजन (wscript.ScriptName, "") (0)

    'बाहरी DLL और ICAM नाम को .CS फ़ाइल से प्राप्त करें
    '################################################# ######
    कॉन्स्ट OPEN_FILE_FOR_READING = 1
    ObjInputFile = fso.OpenTextFile (name_ & ".cs", 1) सेट करें

    'एआरएआरवाई में पढ़ते हुए पढ़िए
    '#############################
    इनपुटडेटा = स्प्लिट (objInputFile.ReadAll, vbNewline)

    प्रत्येक strData के लिए inputData में

        अगर छोड़ दिया (strData, 7) = "// + ref>" तब 
            csc_references = csc_references और "/ संदर्भ:" और ट्रिम (बदलें (strData, "// + ref>", "") और ""
        अगर अंत

        अगर छोड़ दिया (strData, 7) = "// + res>" तब 
            csc_resources = csc_resources & "/ resource:" और ट्रिम (बदलें (strData, "// + res>", "") और ""
        अगर अंत

        अगर छोड़ दिया (strData, 7) = "// + ico>" तब 
            csc_icon = "/ win32icon:" और ट्रिम (बदलें (strData, "// + ico>", "")) और ""
        अगर अंत
    आगे

    objInputFile.Close


    'संकलन संकलन करें
    '################
    oShell.ShellExecute "c: \ windows \ microsoft.net \ फ्रेमवर्क \ v3.5 \ csc.exe", "/ चेतावनी: 1 / लक्ष्य: exe" और csc_references और csc_resources और csc_icon & "" & name_ & ".cs"। , "", "रनस", २


    WScript.Quit (0)

0

यह संभव है, लेकिन यह सब आसान नहीं है, सी # में एक संकर देशी / प्रबंधित विधानसभा बनाने के लिए। क्या आप C ++ का उपयोग कर रहे थे, इसके बजाय यह बहुत आसान होगा, क्योंकि विज़ुअल C ++ कंपाइलर हाइब्रिड असेंबलियों को आसानी से कुछ भी बना सकता है।

जब तक आपको एक हाइब्रिड असेंबली बनाने की सख्त आवश्यकता नहीं है, मैं मुसिएनेसिस से सहमत हूं कि यह वास्तव में सी # करने के लिए परेशानी के लायक नहीं है। यदि आपको इसे करने की आवश्यकता है, तो संभवतः इसके बजाय C ++ / CLI पर जाएं।


0

आम तौर पर आपको असेंबली मर्ज करने के लिए पोस्ट बिल्ड टूल के कुछ रूप की आवश्यकता होती है जैसे आप वर्णन कर रहे हैं। Eazfuscator (eazfuscator.blogspot.com/) नामक एक नि: शुल्क उपकरण है, जिसे बायटेकोड मैनबलिंग के लिए डिज़ाइन किया गया है जो विधानसभा विलय को भी संभालता है। आप अपनी असेंबलियों को मर्ज करने के लिए Visual Studio के साथ पोस्ट बिल्ड कमांड लाइन में इसे जोड़ सकते हैं, लेकिन किसी भी गैर-ट्रिबल असेंबली मर्जिंग परिदृश्य में उत्पन्न होने वाले मुद्दों के कारण आपका माइलेज अलग-अलग होगा।

आप यह देखने के लिए भी जांच कर सकते हैं कि क्या बिल्ड अनटैलिटी बनाते हैं NANT में निर्माण के बाद असेंबलियों को मर्ज करने की क्षमता है, लेकिन मैं खुद NANT से इतना परिचित नहीं हूं कि यह कह सके कि कार्यक्षमता बनी है या नहीं।

कई विज़ुअल स्टूडियो प्लगइन्स भी हैं जो एप्लिकेशन के निर्माण के हिस्से के रूप में असेंबली मर्जिंग प्रदर्शन करेंगे।

वैकल्पिक रूप से यदि आपको स्वचालित रूप से करने की आवश्यकता नहीं है, तो ILMerge जैसे कई उपकरण हैं जो एक ही फ़ाइल में .net असेंबलियों को मर्ज कर देंगे।

असेंबली को मर्ज करने के साथ सबसे बड़ा मुद्दा यह है कि क्या वे किसी भी समान नामस्थान का उपयोग करते हैं। या इससे भी बदतर, एक ही dll के विभिन्न संस्करणों का संदर्भ (मेरी समस्याएं आमतौर पर Nnnit dll फ़ाइलों के साथ थीं)।


1
Eazfuscator सिर्फ IlMerge, AFAIK को कॉल करेगा।
बॉबी

+1 बॉबी। मुझे वह याद रखना चाहिए था। आप के लिए सभी Eazfucator के बारे में अधिक सामान्य कॉन्फ़िगरेशन फ़ाइल के साथ ILMerge में वास्तविक कॉल को सार है।
wllmsaccnt
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.