如何在wpf / winforms应用程序中将DLL与.exe结合使用(带图片)

如何将多个dll组合到主.exe文件中? (不使用第三方程序)

更新

如果您想要一个简单的工具来合并程序集而不必担心任何工作,那么Fody.Costura是您的最佳选择,因为您只需要包含dll并将其Build Action更改为Embedded Resource会马上工作。


1 – 创建一个包含所有Dll的文件夹,或者根据需要单独放置它们 添加Dll

2 – 单击“解决方案资源管理器”中的每个DLL,并确保它们具有这些属性

  • 构建操作=嵌入式资源

  • 复制到输出目录=不复制

改变他们的构建行动

3 – 转到:项目>属性>引用,并确保添加的每个Dll都与程序集具有相同的名称,如下所示:

参考文献: –

参考名称= Dll名称

在Solution Explorer中: –

参考名称= Dll名称

注意 :-

最好在引用中使copy local = True,因为每次发布项目时它都会为您提供更新的DLL

现在,此时您已将DLL添加到EXE中,现在剩下的就是告诉程序如何从EXE读取这些DLL(这就是为什么我们进行构建操作=嵌入式资源)

4 – 在解决方案资源管理器中打开(Application.xaml.vb)文件(c#中的[App.xaml.cs])
要么
转至:项目>属性>应用程序>查看应用程序事件
申请活动

现在在这个页面中我们将处理应用程序的第一个事件(构建事件),告诉程序如何处理我们在使用AssemblyResolve事件加载/读取它们之前添加为DLL的程序集

有关AssemblyResolve事件的更多信息,请查看此MSDN页面https://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve(v=vs.110).aspx

5 – 现在到代码部分:
首先导入此命名空间

vb.net

 Imports System.Reflection 

C#

 using System.Reflection; 

在构造函数(vb中的[Sub New])中添加此代码

Vb.net

  Public Sub New() AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnResolveAssembly End Sub 

C#.NET

 public App() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; } 

然后添加OnResolveAssembly函数
vb.net

 '''  ''' Tells the program that the Assembly it's Seeking is located in the Embedded resources By using the '''  Function To get All the Resources '''  '''  '''  '''  ''' Note that this event won't fire if the dll is in the same folder as the application (sometimes) Private Shared Function OnResolveAssembly(sender As Object, args As ResolveEventArgs) As Assembly Try 'gets the main Assembly Dim parentAssembly = Assembly.GetExecutingAssembly() 'args.Name will be something like this '[ MahApps.Metro, Version=1.1.3.81, Culture=en-US, PublicKeyToken=null ] 'so we take the name of the Assembly (MahApps.Metro) then add (.dll) to it Dim finalname = args.Name.Substring(0, args.Name.IndexOf(","c)) & ".dll" 'here we search the resources for our dll and get the first match Dim ResourcesList = parentAssembly.GetManifestResourceNames() Dim OurResourceName As String = Nothing '(you can replace this with a LINQ extension like [Find] or [First]) For i As Integer = 0 To ResourcesList.Count - 1 Dim name = ResourcesList(i) If name.EndsWith(finalname) Then 'Get the name then close the loop to get the first occuring value OurResourceName = name Exit For End If Next If Not String.IsNullOrWhiteSpace(OurResourceName) Then 'get a stream representing our resource then load it as bytes Using stream As Stream = parentAssembly.GetManifestResourceStream(OurResourceName) 'in vb.net use [ New Byte(stream.Length - 1) ] 'in c#.net use [ new byte[stream.Length]; ] Dim block As Byte() = New Byte(stream.Length - 1) {} stream.Read(block, 0, block.Length) Return Assembly.Load(block) End Using Else Return Nothing End If Catch ex As Exception Return Nothing End Try End Function 

C#.NET

 ///  /// Tells the program that the Assembly its Seeking is located in the Embedded resources By using the ///  Function To get All the Resources ///  ///  ///  ///  /// Note that this event won't fire if the dll is in the same folder as the application (sometimes) private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) { try { //gets the main Assembly var parentAssembly = Assembly.GetExecutingAssembly(); //args.Name will be something like this //[ MahApps.Metro, Version=1.1.3.81, Culture=en-US, PublicKeyToken=null ] //so we take the name of the Assembly (MahApps.Metro) then add (.dll) to it var finalname = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll"; //here we search the resources for our dll and get the first match var ResourcesList = parentAssembly.GetManifestResourceNames(); string OurResourceName = null; //(you can replace this with a LINQ extension like [Find] or [First]) for (int i = 0; i <= ResourcesList.Count - 1; i++) { var name = ResourcesList(i); if (name.EndsWith(finalname)) { //Get the name then close the loop to get the first occuring value OurResourceName = name; break; } } if (!string.IsNullOrWhiteSpace(OurResourceName)) { //get a stream representing our resource then load it as bytes using (Stream stream = parentAssembly.GetManifestResourceStream(OurResourceName)) { //in vb.net use [ New Byte(stream.Length - 1) ] //in c#.net use [ new byte[stream.Length]; ] byte[] block = new byte[stream.Length]; stream.Read(block, 0, block.Length); return Assembly.Load(block); } } else { return null; } } catch (Exception ex) { return null; } } 

6 - 现在发布应用程序或构建它,你的所有dll将嵌入一个EXE文件中(加载它们会有一些额外的毫秒延迟)

更新DLL

1 - 只需将新dll拖放到解决方案资源管理器中,与旧dll相同的文件夹然后接受覆盖(确保检查[Build Action = Embedded Resources]和[Copy To Output Directory = Do copy copy])

改变他们的构建行动

添加新的DLL

只需重复步骤1 => 3

积分:

http://richarddingwall.name/2009/05/14/wpf-how-to-combine-mutliple-assemblies-into-a-single-exe/

*随意询问您是否有任何问题

无法让bigworld12回答为我工作,但我找到了这个链接 ,它对我来说非常有效。

基本上,页面的要点是卸载您的项目并将以下代码添加到您的csproj文件中

    %(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)     

在这行代码下面。

完成后,重新加载项目并向其添加新类,并将以下代码添加到新类中。

 [STAThread] public static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; App.Main(); // Run WPF startup code. } private static Assembly OnResolveAssembly(object sender, ResolveEventArgs e) { var thisAssembly = Assembly.GetExecutingAssembly(); // Get the Name of the AssemblyFile var assemblyName = new AssemblyName(e.Name); var dllName = assemblyName.Name + ".dll"; // Load from Embedded Resources - This function is not called if the Assembly is already // in the same folder as the app. var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(dllName)); if (resources.Any()) { // 99% of cases will only have one matching item, but if you don't, // you will have to change the logic to handle those cases. var resourceName = resources.First(); using (var stream = thisAssembly.GetManifestResourceStream(resourceName)) { if (stream == null) return null; var block = new byte[stream.Length]; // Safely try to load the assembly. try { stream.Read(block, 0, block.Length); return Assembly.Load(block); } catch (IOException) { return null; } catch(BadImageFormatException) { return null; } } } // in the case the resource doesn't exist, return null. return null; } 

保存您的类,打开项目的属性菜单,选择启动对象combobox然后从列表中选择您刚创建的类的名称。

剩下的就是构建你的项目了。