将.NET应用合并打包成单文件的两个方法

时间:09/16/2024 15:24:04   作者:ChenReal    阅读:14

前阵子,答应了帮一位哥们做一个桌面应用工具。

好吧,说干就干!花了一个周末的时候,应用功能的开发算是搞定了,剩下来就是交付的问题了。这时,我看到release目录里一堆的dll,程序代码的洁癖再也压制不住了。于是,临时给自己增加一个目标:把这些丑陋的dll给隐藏起来,放在一个子目录里,当然最好是全部打包成一个exe文件。

如果是.NET Core开发的应用,那就很好办,打包指令加上self-contained就可以了。例如:

dotnet publish -c Release -r win-x64 --self-contained

好是不死,因为组件依赖的原因,我不得不使用.NET Framework。因此,只能求助互联网给我思路了。很快我便找到了两方案,都能够完美解决我的需求。

下面我就分别介绍一下吧。

一、ILMerge

获得ILMerge

%MSBUILD% ILMerge\ILMerge.csproj /t:Rebuild /p:Configuration=Release;OutDir=.\bin


#### 创建项目

创建一个名为`MergeAppDemo`的项目,项目中引用了我们熟悉的第三方库`Newtonsoft.Json`。然后正常编译出来的内容如下:

![image.png](https://qqcdn.chenreal.com/blog/202409/133709484971834755_gqC.png)

#### ILMerge打包脚本
执行以下命令

ILMerge.exe /log:merge.log /t:winexe /out:target\MergeAppDemo.exe source\MergeAppDemo.exe source\Newtonsoft.Json.dll


几秒钟后,得到一个新的可执行文件。并且我们发现了它的Size,增大了不少。看来`Newtonsoft.Json.dll`已经被打包在其中了!

![image.png](https://qqcdn.chenreal.com/blog/202409/133709487062209991_Vhk.png)

双击运行`MergeAppDemo.exe`,太好了,成功了!

#### 将ILMerge脚本整合项目工程
如果大家觉得每次生成编译还要额外多执行一次ILMerge脚本太过麻烦,我们可以将脚本写入在项目工程配置里,那么就可以简化成,每次Release发布成功后,自动执行ILMerge脚本,一气呵成。

首先,用文本编辑器打开工程文件`MergeAppDemo.csproj`,找到编译参数的配置节点,添加`PostBuildEvent`的脚本内容。

AnyCPU pdbonly true bin\Release\ TRACE prompt 4

<PostBuildEvent>
ILMerge.exe /log:merge.log /t:winexe /out:$(ProjectDir)bin\MergeAppDemo.exe $(ProjectDir)bin\Release\MergeAppDemo.exe $(ProjectDir)bin\Release\Newtonsoft.Json.dll


## 二、Costura.Fody

#### 安装Costura.Fody

要使用Costura.Fody,你首先需要将其安装到你的项目中。你可以通过NuGet包管理器来安装它。在你的Visual Studio中,打开“包管理器控制台”,然后输入以下命令:

Install-Package Costura.Fody ```

编译项目

安装好Costura.Fody之后,无需做任何配置,直接编译项目。转到在bin/Release目录,就可以找到已经打包好的exe文件,而且Size比ILMerge生成的更小。

image.png

看起来十分完美,同样双击运行MergeAppDemo.exe,也可以正常执行!

总结

本文介绍了两种.NET应用程序的打包工具,分别是ILMerge和Costura.Fody。他们都能完成目标,把各种依赖的dll和其他资源全部打包在单一的exe文件中。

我个人推荐Costura.Fody。因为相对而言Costura.Fody实现更加简单方便:

  • 配置简单,直接Nuget引入即可,不像ILMerge还需要额外编写脚本
  • 而且编译打包速度更快,几乎感觉不到因打包产生的延迟
  • 生成文件的Size更小,似乎Costura.Fody还做了一些裁剪

 

评论
0/200