Merging a WPF application into a single EXE(WPF应用程序合并成单个Exe文件)
I always dislike handing off little applications to people. Not because I can’t, but because of the steps involved to make sure it all just works. Small apps are the most problematic because I never want to take the time to create a whole installer project for just a few assemblies, and packaging up a zip file must be accompanied by “Unzip this into a folder in your programs directory and create a shortcut…” which brings us back to the whole installer business we started with.
There are a few tools already out there such as ILMerge by Microsoft Research (Which works great for most .NET-y things, but chokes on WPF applications) and a few paid tools by third party vendors that you could fork over a few hundred for to get. But, I’m a developer, which means I want to do it the Hard Way™. I did a little research and found the following blog posts on setting up and merging in DLL’s as resources into the main assembly and then extracting and loading them into memory when you run your application.
Links:
- http://richarddingwall.name/2009/05/14/wpf-how-to-combine-mutliple-assemblies-into-a-single-exe/
- http://blog.mahop.net/post/Merge-WPF-Assemblies.aspx
- http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application
There were a few things I didn’t like about each solution. The first one (richarddingwall.name) ends up having you directly adding the .dll’s as resources directly. I hate maintaining things manually, especially when it will run fine on my machine but break when when I move it somewhere else because I forgot to update the resources when I added a new project. The one from blog.mahop.net builds on the previous one and changes the resolve location to a custom class with its own startup method. Better, because it resolves the resources earlier. Finally, the one from Daniel Chambers (digitallycreated.net) added in the final piece that automatically including the assemblies as resources. Unfortunately, the way he looks for culture specific assemblies didn’t work and I had to remove / change it to be closer to the one on mahop.net.
Final solution I’m currently using is as follows:
To the main executable project, unload and edit the .csproj file, and below the following line:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Add this XML to the project file, save, and load it back up.
<Target Name="AfterResolveReferences">
<ItemGroup>
<EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
<LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Target>
It should look something like this when your done:

You’ll then add a new code file to the main project and add the following code to it (modified to fit how your application is named / structured, in a WPF application, a good place to put it would be App.xaml.cs):
[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;
}
Finally, make sure you update the target method for your main application to be the main method for the project you just added:

And, that’s it!
When you build your application you’ll still see all the assemblies in the output directory, but you should be able to take just the executable, move it somewhere else, and run it just as it is.
Merging a WPF application into a single EXE(WPF应用程序合并成单个Exe文件)的更多相关文章
- 将visual sdudio+Qt5.12 制作的程序打包成单个exe
在GitHub上下载了个qt程序,由于C++不太会,经过安装qt.修改编码等一系列操作终于可以运行了. 生成的exe在运行时依赖很多dll或者图片文件,直接拷贝到其他电脑上无法运行,可以将依赖的dll ...
- C#程序(含多个Dll)合并成一个Exe
把C#程序(含多个Dll)合并成一个Exe的超简单方法 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. 但是,很多时候我们本想开发一款只需要一 ...
- 将WinForm程序(含多个非托管Dll)合并成一个exe的方法
原文:将WinForm程序(含多个非托管Dll)合并成一个exe的方法 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. ILMerge能把托管dl ...
- 利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe)
原文:利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe) 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了.这 ...
- 如何将你写的脚本程序打包成一个exe可执行程序
编写的程序打包成一个exe文件,随时可以双击执行,想想是不是很酷.接下来我们一起看一下如何将自己编写的程序打包为一个exe的可执行程序. 将程序打包成exe的好处 除了满足自己的成就感以外, ...
- 用Pyinstaller把Python3.7程序打包成可执行文件exe
1.通过pip3 install pyinstaller 安装成功 2.然后执行命令,首先:需要切换到程序所在的目录 执行命令 pyinstaller -F -w <文件名.py>,-F代 ...
- 把C#程序(含多个Dll)合并成一个Exe的超简单方法
开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. 但是,很多时候我们本想开发一款只需要一个exe就能完美运行的小工具.那该怎么办呢? 下文介绍一种超 ...
- 使用rar把程序打包成一个exe
根目录--全部文件--右键添加到压缩文件 常规--创建自解压压缩文件 高级--自解压选项 解压路径--Finger(自己写)--在"Program Files"中创建 设置--解压 ...
- 调用cmd.exe执行pdf的合并(pdftk.exe)
今天调查一个pdf文件的抽取,合并功能,用到下面这个工具(pdftk): https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/ 在cmd.exe里执 ...
随机推荐
- Web用户控件
用户控件是个什么东西?自定义的反复重用的控件集合 注意:创建好用户控件后,必须添加到其他web页中才能显示出来,不能直接作为一个网页来显示,因此也就不能设置用户控件为“起始页”. 用户控件与ASP.N ...
- ASP.NET - 使用 XML
对XML文件进行简单的增加,删除,修改,查看等功能. XML代码: <?xml version="1.0" encoding="UTF-8"?> & ...
- C# - 数据库存取图片
1.创建数据表 CREATE TABLE Tb_pic ( ID int primary key identity(1, 1) not null, PictureBox varchar(max) ) ...
- HDU 4350 Card
打表找规律,比赛应付了一下,其实还可以把内存再优化一半掉,下面的0都是手动填充的,可以优化掉 题意: T个测试数据 下面52个数字表示 从栈顶到栈底的52个数 n l r表示 从栈顶下数 [l,r] ...
- Codility上的问题 (16) Omicron 2012
比较无聊的题,求斐波那契数的第N^M项. f(0) = 0, f(1) = 1, f(n) = f(n - 1) + f(n - 2),结果对10000103取模. N, M在[0..10^7]之间. ...
- HDU 4669 Mutiples on a circle (DP , 统计)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题意:给出一个环,每个点是一个数字,取一个子串,使 ...
- 单链表的插入删除操作(c++实现)
下列代码实现的是单链表的按序插入.链表元素的删除.链表的输出 // mylink.h 代码 #ifndef MYLINK_H #define MYLINK_H #include<iostream ...
- 修改合同号的bapi
这个例子是在合同号中新增项目号: 1.先要读取该合同号的信息用一个BAPI BAPI_CONTRACT_GETDETAIL 2.调用修改合同号的BAPI. 代码如下: REPORT ztest_cla ...
- Ubuntu 环境安装整理
Ubuntu11.04下Java开发环境搭建和配置 转自:http://guoyunsky.iteye.com/blog/1175861 类似的搭建,网上一搜一大把,但每次去搜索比较麻烦.我这里就整理 ...
- UIPageControl的一个Demo
本篇文章只是记录了一个自定义UIPageControl 的制作,其实很简单的 源码在底部会奉上链接,还望多多交流,多多支持. 首先效果图如下: 首先先做一个UISCrollView // 建议这样 ...