将dll与wpf合并成一个.exe文件

我目前正在做一个项目,我们有很多的依赖关系。 我想将所有引用的dll编译到.exe中,就像使用embedded式资源一样。 我已经尝试ILMerge,但它不能处理.xaml资源。

所以我的问题是:有没有办法将WPF项目与多个依赖关系合并成一个.exe文件?

.NET反应器具有合并组件的function,而且其价格并不昂贵。

http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application

这对我来说就像一个魅力:),它是完全免费的。

添加代码以防博客消失。

1)将此添加到您的.csproj文件中:

 <Target Name="AfterResolveReferences"> <ItemGroup> <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> </Target> 

2)让你的Main Program.cs看起来像这样:

 [STAThreadAttribute] public static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; App.Main(); } 

3)添加OnResolveAssembly方法:

 private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); AssemblyName assemblyName = new AssemblyName(args.Name); var path = assemblyName.Name + ".dll"; if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path); using (Stream stream = executingAssembly.GetManifestResourceStream(path)) { if (stream == null) return null; var assemblyRawBytes = new byte[stream.Length]; stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length); return Assembly.Load(assemblyRawBytes); } } 

Costura是一个开源工具,用于处理合并wpf程序集。

https://github.com/Fody/Costura#how-it-works

{smartassembly}就是这样一个产品。 它可以隐藏或embedded你的DLL。

试试这个: http : //www.smartassembly.com/

你也可以在你的应用程序上做很多改进,以便运行得更快。

是的。 你可以使用它的WPF。

更新2015年8月6日:ILRepack 2.0.0(这是ILMerge的开源替代品)现在支持大部分WPF案例合并: https ://twitter.com/Gluckies/status/607680149157462016

正如在ILMerge网站上发布的那样 ,把这些DLL作为资源从杰弗里·里希特(Jeffrey Richter)

许多应用程序由依赖于许多DLL文件的EXE文件组成。 部署此应用程序时,必须部署所有文件。 但是,有一种技术可以用来部署一个EXE文件。 首先,找出您的EXE文件所依赖的所有DLL文件,这些文件不作为Microsoft .NET Framework本身的一部分提供。 然后将这些DLL添加到您的Visual Studio项目。 对于添加的每个DLL文件,显示其属性,并将其“Build Action”更改为“Embedded Resource”。这会导致C#编译器将DLL文件embedded到EXE文件中,并且可以部署这个EXE文件。 在运行时,CLR将无法find依赖的DLL程序集,这是一个问题。 为了解决这个问题,当你的应用程序初始化时,用AppDomain的ResolveAssembly事件注册一个callback方法。 代码应该是这样的:

 AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { String resourceName = "AssemblyLoadingAndReflection." + 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); } }; 

现在,线程首次调用一个引用依赖DLL文件中的types的方法时,AssemblyResolve事件将被引发,上面显示的callback代码将find所需的embedded式DLL资源,并通过调用Assembly的Load方法的重载来加载它以Byte []作为参数。

使用Costura.Fody – 它可以作为Nuget Pkg,以最好的和最简单的方式来embedded资源在您的大会。

 Install-Package Costura.Fody 

将其添加到项目后,它会自动将所有添加的引用embedded到主程序集中。

尝试.Netz( http://madebits.com/netz/ ) – 它是免费的(如啤酒),并做一些很好的事情,如果你的目标是一个EXE。

下面是Matthieu引用代码的一个调整版本,它不需要知道命名空间来提取代码。 对于WPF,将其放入应用程序启动事件代码中。

 AppDomain.CurrentDomain.AssemblyResolve += (s, args) => { // Note: Requires a using statement for System.Reflection and System.Diagnostics. Assembly assembly = Assembly.GetExecutingAssembly(); List<string> embeddedResources = new List<string>(assembly.GetManifestResourceNames()); string assemblyName = new AssemblyName(args.Name).Name; string fileName = string.Format("{0}.dll", assemblyName); string resourceName = embeddedResources.Where(ern => ern.EndsWith(fileName)).FirstOrDefault(); if (!string.IsNullOrWhiteSpace(resourceName)) { using (var stream = assembly.GetManifestResourceStream(resourceName)) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); var test = Assembly.Load(assemblyData); string namespace_ = test.GetTypes().Where(t => t.Name == assemblyName).Select(t => t.Namespace).FirstOrDefault(); #if DEBUG Debug.WriteLine(string.Format("\tNamespace for '{0}' is '{1}'", fileName, namespace_)); #endif return Assembly.Load(assemblyData); } } return null; }; 

为了在编译时使它们可用,我创build了一个名为ExternalDLLs的文件夹,并将dll复制到那里,并将它们设置为EmbeddedResource,如上所述。 要在代码中使用它们,您仍然需要设置对它们的引用,但将Copy local设置为False。 为了让代码无误地编译,你还需要在你的代码中使用stats来设置dll的命名空间。

这是一个小工具,它通过embedded的资源名称进行旋转,并在输出窗口中显示其名称空间。

 private void getEmbeddedResourceNamespaces() { // Note: Requires a using statement for System.Reflection and System.Diagnostics. Assembly assembly = Assembly.GetExecutingAssembly(); List<string> embeddedResourceNames = new List<string>(assembly.GetManifestResourceNames()); foreach (string resourceName in embeddedResourceNames) { using (var stream = assembly.GetManifestResourceStream(resourceName)) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); try { var test = Assembly.Load(assemblyData); foreach (Type type in test.GetTypes()) { Debug.WriteLine(string.Format("\tNamespace for '{0}' is '{1}'", type.Name, type.Namespace)); } } catch { } } } } 
  1. 将其添加到.csprofj文件中:

>

 <Target Name="AfterResolveReferences"> <ItemGroup> <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> </Target> 
  1. 右键单击project / properties / application / starup对象/selectSinhro.Program

  2. 将此添加到您的program.cs文件中:

    使用System.Reflection; 使用System.IO; 使用System.Globalization;

     [STAThreadAttribute] static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; ... private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); AssemblyName assemblyName = new AssemblyName(args.Name); string path = assemblyName.Name + ".dll"; if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) { path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path); } using (Stream stream = executingAssembly.GetManifestResourceStream(path)) { if (stream == null) return null; byte[] assemblyRawBytes = new byte[stream.Length]; stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length); return Assembly.Load(assemblyRawBytes); } } 

来源: http : //www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application