写在前面
承接篇6。本篇讲 WinForms 应用怎么打包交付给用户:单文件发布、ClickOnce、自动更新、签名。
WinForms 部署比 Web 复杂:你要把 exe + 依赖装到用户机器、管更新、过 SmartScreen。.NET 8 时代,单文件发布 + ClickOnce 是主力,MSIX 是新选择。
一、dotnet publish:单文件发布
.NET SDK 的 dotnet publish 把应用打包成可分发的产物。最实用的是单文件(self-contained exe,用户机器不用装 .NET):
1
2
3
| dotnet publish -c Release -r win-x64 --self-contained true \
-p:PublishSingleFile=true \
-p:IncludeNativeLibrariesForSelfExtract=true
|
参数:
| 参数 | 含义 |
|---|
-c Release | Release 编译 |
-r win-x64 | 目标运行时(WinForms 只能 win-x64/x86) |
--self-contained true | 自包含(带 .NET 运行时,用户免装) |
PublishSingleFile | 打成单个 exe |
IncludeNativeLibrariesForSelfExtract | 原生库也塞进单文件 |
1
2
3
| 产物:bin/Release/net8.0-windows/win-x64/publish/MyApp.exe
→ 一个文件(运行时解压到临时目录),双击即跑
→ 拷给用户、放共享盘、U 盘分发都行
|
自包含单文件约 150MB+(含 .NET 运行时)。要更小用 --self-contained false(框架依赖,~1MB,但用户机器要装 .NET Desktop Runtime)。
二、ReadyToRun / Trim
ReadyToRun(R2R):预编译成原生机器码,启动更快,体积大些:
1
2
| dotnet publish -c Release -r win-x64 --self-contained true \
-p:PublishSingleFile=true -p:PublishReadyToRun=true
|
1
2
3
4
| ReadyToRun:
预 JIT 成原生码,启动快 ~20-30%
体积大 ~30%
→ 启动敏感的工具类应用值得开
|
Trim(裁剪):移除没用到的代码,减小体积。WinForms 对 Trim 支持差(大量反射 + 设计器),别开:
1
2
| # WinForms 别开 Trim(会运行时缺类型崩)
-p:PublishTrimmed=true # ✗ WinForms 不推荐
|
WinForms 还不能完全 AOT(NativeAOT),反射 / 设计器 / 资源加载不兼容。要做原生编译,考虑迁 MAUI/WinUI。
三、ClickOnce:老牌自动更新
ClickOnce(.NET Framework 2.0 起)是 WinForms/WPF 的"零摩擦安装 + 自动更新"方案:用户点网页链接 → 装到用户目录(不需管理员)→ 每次启动检查更新。
.NET 8 下 ClickOnce 仍支持(VS 项目属性 → Publish,或 publish 配置),流程:
1
2
3
4
| 1. dotnet publish 生成 ClickOnce 清单(.application / .manifest)
2. 放到 Web 服务器 / 共享盘 / Azure Blob
3. 用户访问 install.htm → 下载安装
4. 程序每次启动检查更新 → 有新版自动下载替换
|
VS 里:项目属性 → Publish → ClickOnce 发布向导,设发布位置、更新策略(启动时检查 / 间隔 N 天)、签名。
1
2
3
4
5
| ClickOnce 适合:
✓ 企业内部工具(用户点链接即装,自动更新,不需管理员权限)
✓ 频繁更新的小工具
✗ 需要系统服务 / 驱动 / 深度注册表的(ClickOnce 沙箱限制)
✗ 需要"商店分发"的现代场景(用 MSIX)
|
ClickOnce 的更新是"替换整个应用",大应用更新慢;但它仍是 WinForms 内网分发的最省心方案。
四、MSIX:现代打包
MSIX(Windows 10+)是微软主推的现代应用包格式:干净安装/卸载、沙箱、商店分发、自动更新。
1
2
3
4
5
6
| MSIX vs ClickOnce:
MSIX 现代包格式,干净安装,商店分发,需打包工程
ClickOnce 老牌,零摩擦,内网/网页分发,更新简单
→ 想进 Microsoft Store / 企业私店 → MSIX
→ 内网快速分发 + 自动更新 → ClickOnce 够用
|
打包用 Visual Studio 的"Windows 应用程序打包项目"(WAP)或 MakeAppx 工具。MSIX 要签名(证书),企业分发用内部 CA,商店分发用 MS Store 关联。
五、自动更新实现
不用 ClickOnce/MSIX,自己实现"启动时检查 + 下载 + 替换":
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // 简化版自动更新
private async void Form1_Load(object sender, EventArgs e)
{
var latest = await CheckLatestVersionAsync();
if (latest.Version > CurrentVersion)
{
if (MessageBox.Show($"发现新版本 {latest.Version},更新?",
"更新", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
await DownloadAndUpdateAsync(latest.Url);
Application.Restart(); // 重启加载新版本
}
}
}
|
要点:
- 版本号放一个可访问的地方(API/文件),启动时拉取对比。
- 下载新 exe 到临时目录,替换主程序(可能需 bat 脚本辅助,运行中的 exe 不能直接覆盖)。
- 用 ClickOnce/MSIX 省事;自实现适合特殊场景。
开源方案:Velopack、Squirrel.Windows,封装了检查/下载/替换/快捷方式全套。
六、代码签名
Windows SmartScreen 对未签名 exe 会弹警告(蓝屏"Windows 已保护你的电脑")。企业/正式分发必须签名:
1
2
3
4
| 签名方式:
代码签名证书(EV / OV)+ signtool.exe
EV 证书 立即过 SmartScreen(贵,要硬件 token)
OV 证书 需积累信誉,初期仍弹 SmartScreen
|
1
2
| signtool sign /fd sha256 /a /tr http://timestamp.sectigo.com /td sha256 \
/n "Your Company Name" MyApp.exe
|
内部分发用自签名证书(企业 CA 推到用户机器的根证书);公网分发用商业代码签名证书。
七、部署选型
1
2
3
4
5
6
7
8
| 你的场景 推荐
──────────────────────────────────────────────────────
个人/小工具,拷给朋友 单文件 exe(U 盘/网盘)
企业内部,频繁更新 ClickOnce(网页/共享盘 + 自动更新)
进 Microsoft Store / 企业私店 MSIX
要启动快 单文件 + ReadyToRun
要正式分发,过 SmartScreen 商业代码签名 + 单文件/MSIX
自动更新不想自己造 Velopack / Squirrel
|
八、小结
1
2
3
4
5
6
7
| WinForms 部署核心:
✓ dotnet publish --self-contained + PublishSingleFile = 单 exe 分发
✓ ReadyToRun 加速启动(体积换启动);Trim 别开
✓ ClickOnce:内网零摩擦安装 + 自动更新(最省心)
✓ MSIX:现代包,适合商店/企业私店
✓ 自动更新:ClickOnce/MSIX 自带;或 Velopack/Squirrel
✓ 正式分发必须代码签名(过 SmartScreen)
|
下一篇:WinForms vs WPF——两个框架对照、选型决策、迁移路径,系列收官。