如何将多个dll合并到主.exe文件中? (不使用第三方程序)
最佳答案
更新资料
如果您想要一个简单的工具来合并程序集而不必担心做任何工作,那么Fody.Costura是您的最佳选择,因为您需要做的就是仅包含dll,并将其Build Action更改为Embedded Resource,将立即工作。
1-创建一个包含所有Dll的文件夹,或根据需要将它们分别放置
2-从“解决方案资源管理器”中单击每个DLL,并确保它们具有这些属性
构建操作=嵌入式资源
复制到输出目录=不复制
3-转到:“项目”>“属性”>“引用”,并确保添加的每个Dll都具有与程序集相同的名称,如下所示:
在参考文献中:
在解决方案资源管理器中:
注意 :-
最好在引用中将副本设为局部= True,因为这样做会给
每次发布项目时,您都会获得更新的DLL
现在,您已经将DLL添加到EXE了,剩下的就是告诉程序如何从EXE读取这些DLL(这就是我们进行构建操作=嵌入资源的原因)
4-在解决方案资源管理器中,打开您的(Application.xaml.vb)文件(在c#中为[App.xaml.cs])
要么
转到:项目>属性>应用程序>查看应用程序事件
现在,在此页面中,我们将处理应用程序的第一个事件(构造事件),以告诉程序在使用AssemblyResolve
事件加载/读取它们之前,如何处理我们作为DLL添加的程序集。
检查此MSDN页面以获取有关AssemblyResolve事件的更多信息
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
''' <summary>
''' Tells the program that the Assembly it's Seeking is located in the Embedded resources By using the
''' <see cref="Assembly.GetManifestResourceNames"/> Function To get All the Resources
''' </summary>
''' <param name="sender"></param>
''' <param name="args"></param>
''' <returns></returns>
''' <remarks>Note that this event won't fire if the dll is in the same folder as the application (sometimes)</remarks>
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
/// <summary>
/// Tells the program that the Assembly its Seeking is located in the Embedded resources By using the
/// <see cref="Assembly.GetManifestResourceNames"/> Function To get All the Resources
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
/// <remarks>Note that this event won't fire if the dll is in the same folder as the application (sometimes)</remarks>
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相同的文件夹拖放到解决方案资源管理器中,然后接受覆盖(请确保检查[生成操作=嵌入式资源]和[复制到输出目录=不复制])
添加新的DLL
只需重复步骤1 => 3
学分:
http://richarddingwall.name/2009/05/14/wpf-how-to-combine-mutliple-assemblies-into-a-single-exe/
*随时询问您是否有任何问题
关于c# - 如何在wpf/winforms应用程序(带有图片)中将DLL与.exe组合在一起,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27891550/