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

时间:2024-09-16 15:24   作者:ChenReal    阅读:63

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

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

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

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

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

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

一、ILMerge

获得ILMerge

  • 下载源代码

git clone https://github.com/dotnet/ILMerge.git

  • 编译代码
SET MSBUILD="C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MsBuild.exe"

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

创建项目

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

image.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

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

将ILMerge脚本整合项目工程

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

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

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>

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

二、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