为 .NET 应用制作 Windows 安装程序(WPF、WinForms、控制台)
用 dotnet publish 发布 .NET 桌面应用,在依赖框架与独立部署之间做出选择,然后把发布文件夹打包成带快捷方式和卸载程序的 Setup.exe。
更新于 2026年10月31日 · 阅读约 4 分钟
Visual Studio 负责构建你的 WPF 或 WinForms 应用,dotnet publish 则生成一个可以在任何地方运行的文件夹。缺的那一环是安装程序:开始菜单项、Program Files 文件夹、Windows 设置里的卸载条目。老牌的 ClickOnce 和 Visual Studio Installer Projects 仍然存在,但两者都已显得过时。下面是从 .NET 项目到 Setup.exe 最直接的一条路。
第 1 步:发布应用
发布会生成一个包含应用所需全部内容的文件夹。在项目文件夹中运行:
dotnet publish -c Release -r win-x64 --self-contained true
输出位于 bin\Release\net8.0-windows\win-x64\publish\(路径中的目标框架随你的项目而变)。你要分发的就是这个文件夹。
唯一需要认真决定的事:
- 独立部署(
--self-contained true)会打包 .NET 运行时。文件夹有 70 到 150 MB,但在任何 Windows 机器上都能直接运行,无需事先安装任何东西。面向公众分发的软件请选择这一项。 - 依赖框架(
--self-contained false)只有几 MB,但用户必须已安装匹配的 .NET Desktop Runtime,否则应用在首次启动时会弹出下载提示。适合托管机器上的内部工具。
一些有用的选项:
-p:PublishReadyToRun=true对应用进行预编译,启动更快。-p:PublishSingleFile=true把输出合并为一个.exe。它可以用,但有了安装程序就没有理由再用它,而且单文件应用会在首次运行时解包原生库。普通文件夹更简单。- 裁剪(
PublishTrimmed)不支持 WPF 和 WinForms,请保持关闭。
在项目文件中设置应用图标,让发布出来的 .exe 带上它:
<PropertyGroup>
<ApplicationIcon>app.ico</ApplicationIcon>
</PropertyGroup>
从发布文件夹里运行一次发布出来的 .exe,最好在一台没装 Visual Studio 的机器上,确认没有缺少任何东西。
第 2 步:压缩发布文件夹
把 publish` 的*内容*压缩成 zip:.exe、各个 DLL、.deps.json、.runtimeconfig.json 以及所有内容文件。不要包含 .pdb` 文件,除非你希望在客户机器上保留崩溃符号。
第 3 步:构建安装程序
- 把 zip 上传到 ExeTup。它会把你的应用
.exe选为主程序;请确认一下,因为独立部署的发布中包含createdump.exe,而它并不是主程序。 - 填写名称、版本(与项目中的
<Version>保持一致)、发布者和许可协议。 - 经典的 Program Files 桌面应用选择所有用户;客户可能没有管理员权限时选择当前用户。
win-x64发布保持 64 位;win-x86则选择 32 位。- 上传同一个
app.ico,启用快捷方式,然后构建。
下载 Setup.exe,在 Windows 上测试安装和卸载。
.NET 专属说明
- 更新。发布一个版本号更高的新安装程序。覆盖旧版本安装会替换文件;安装程序不包含自动更新通道。
- 设置和数据。把用户数据写入
%APPDATA%或%LOCALAPPDATA%,不要写在.exe旁边。Program Files 对普通用户是只读的,而且卸载程序只会删除它安装的内容。 - 先决条件。独立部署的发布不需要任何其他东西。如果你的应用需要 Visual C++ 运行时或数据库驱动,请在文档中说明;安装程序不会链式调用其他安装程序。
- 代码签名。压缩前先给发布出来的
.exe签名,然后再给下载下来的Setup.exe签名。参见 SmartScreen 指南。
替代方案
- Visual Studio Installer Projects 在 Visual Studio 内部生成 MSI 文件。目前仍以扩展形式提供,功能有限,处理独立部署的发布时很别扭。
- ClickOnce 提供带自动更新的按用户安装,绑定在一台由你维护的 Web 服务器上。
- WiX Toolset 从 XML 构建 MSI 文件,是企业级 MSI 打包的标准。功能强大,学习曲线也同样陡峭。
- MSIX 是 Microsoft 较新的包格式,面向 Microsoft Store 时最合适。
格式何时重要,请参见 MSI 与 EXE 安装程序对比。
常见问题
我应该选择依赖框架还是独立部署?
任何面向公众提供的东西都选独立部署,这样应用无需下载运行时即可运行。IT 部门统一管理 .NET 运行时的机器上的内部工具,可选依赖框架。
安装程序包含 .NET 运行时吗?
如果你以独立部署方式发布,那么包含,因为它是发布文件夹的一部分。安装程序会原样打包 zip 里的所有内容。
我能为组策略生成 MSI 吗?
ExeTup 构建的是 Setup.exe。它可以用 /S 静默安装,这已经覆盖了大多数脚本化部署。对于只接受 MSI 的策略,WiX 才是合适的工具。
这适用于哪些 .NET 版本?
任何能生成发布文件夹的版本:.NET 6、7、8、9 及更高版本,以及用 Visual Studio 构建的 .NET Framework 应用(使用 bin\Release 输出)。
相关指南
- 如何为 Windows 应用制作 Setup.exe(无需编写代码)了解 Setup.exe 实际做了什么、制作安装程序的三种方式,以及如何无需编写安装脚本,几分钟内把应用文件夹变成专业的安装程序。
- MSI 与 EXE 安装程序:你的 Windows 应用该选哪一种?MSI 包与 Setup.exe 的真正区别、IT 部门什么时候确实需要 MSI、MSIX 的定位,以及为什么大多数桌面应用都发布 EXE。
- '"Windows 已保护你的电脑":SmartScreen 警告是什么意思,怎样消除'为什么 Windows 会对新安装程序显示"未知发布者"警告,用户可以点什么,以及代码签名和信誉如何让警告消失。