如何将多个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/

10-12 00:27
查看更多