POST://ilrepack-single-file-packing
带点橘子味的馒头的头像
带点橘子味的馒头

FRONTEND / DESKTOP DEV

返回文章列表

单文件打包 .NET 程序的完整方案:ILRepack + 发布脚本

1 分钟· 621 98 次阅读

做桌面工具的人大概率会遇到同一个问题:程序写好了,但交付物是一堆 DLL 散文件,发给用户要么缺文件要么版本错乱。单文件打包是解决这个问题的标准姿势,本文基于一套 WPF/C# 工具箱的实践经验展开。

为什么用 ILRepack

.NET Framework 4.8 项目没有官方的一键单文件发布(那是 .NET Core/5+ 才有的),社区主流方案是 ILRepack——把多个托管程序集合并成一个。

<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.34.2" />

装上之后可以在 csproj 里配置 AfterBuild 目标,也可以在发布脚本里手动调用,后者更可控。

发布脚本的设计

推荐用 PowerShell 脚本(build-release.ps1)串起整个流程,而不是依赖 IDE 菜单:

param(
    [string]$Configuration = "Release",
    [string]$OutputDir = "dist"
)

# 1. 编译
dotnet build -c $Configuration

# 2. 合并程序集(排除主程序集本身)
& ilrepack /lib:"bin\$Configuration" `
    /out:"$OutputDir\Tool.exe" `
    "bin\$Configuration\Tool.exe" `
    "bin\$Configuration\*.dll"

# 3. 拷贝原生依赖(比如 SQLite、OpenCV 的 native 库)
Copy-Item "bin\$Configuration\native\*" "$OutputDir\" -Recurse

# 4. 产物校验:文件数应为 1(托管)+ N(原生)
Get-ChildItem $OutputDir | Select Name, Length

常见坑

问题 原因与解法
合并后启动报 FileNotFound 有程序集没被合并(动态加载或延迟绑定)→ 检查 App.config 的 probing 路径,或把这些 DLL 加入合并列表
泛型/反射失效 某些库(如 NHibernate)依赖独立程序集边界 → 用 --internalize 前先测功能
配置文件丢失 .config 不算程序集,要单独拷贝
图标/资源文件 WinForms/WPF 资源在 exe 里没问题,但独立资源文件要手动带上

打包前的日志检查

一个容易被忽略的环节:发布前检查代码里残留的调试日志。团队的做法是在发布脚本里加一道静态检查:

# 拒绝包含 Console.WriteLine / Debug.WriteLine 的发布
$violations = Select-String -Path "src\*.cs" -Pattern "Console\.WriteLine|Debug\.WriteLine"
if ($violations) {
    Write-Error "发布前请清理调试日志: $($violations.Count) 处"
    exit 1
}

这比靠自觉可靠得多——CI 或发布脚本会自动拦截。

小结

  • 托管程序集 → ILRepack 合并成单 exe;
  • 原生依赖 → 目录结构保留,独立分发;
  • 发布流程 → 脚本化(编译 → 合并 → 拷贝 → 校验 → 日志检查);
  • 每次发布前打 git tag 存档,方便回滚。

单文件不只是"好看",它把"用户缺 DLL"这类支持成本直接降为零。

相关文章