如何发布和部署一个.NET WPF工具
构建一个小型桌面工具只完成了一半。 将其安装到您的设备上,放置在您可以快速启动它的位置,并保持部署轻量以至于您再也不用考虑它,就是另一半。 太多的开发人员在这一步上过度设计,引入安装程序框架或跨平台工具,但这些工具仅在一台工作站上运行。
在他的视频"如何发布和部署.NET WPF工具"中,Tim Corey演示了如何将他个人的图像查看器应用发布为单个可执行文件,复制到一个文件夹,并通过注册表接入到Windows右键菜单中。 我们将介绍他一路做出的每个决定,从依赖于框架与独立的构建到使工具从任何文件夹中可访问的注册表项。 如果您为自己构建了一个小工具,并希望最简单的部署方式,这篇文章提出了这种方法。
从Visual Studio发布
[1:03 - 1:25] Tim从在Visual Studio中右键点击项目并选择发布开始。 向导显示几个目标(Azure,Docker,ClickOnce),但他绕过所有这些选择文件夹。 对于仅在您自己机器上运行的个人工具,文件夹发布是最直接的路径:它生成的文件可以随意复制而无需任何部署基础设施。
选择文件夹目标后,Tim直接跳转到设置页面,而不是立即进行发布。 输出与他想要的不匹配需要调整默认设置。
依赖于框架 vs. 独立构建
[1:25 - 2:32] 第一个设置是部署模式。 依赖于框架的构建假定.NET SDK或运行时已安装在目标机器上。输出很小,大约200KB,因为它依赖于您系统上存在的共享运行时。
独立构建将整个.NET运行时捆绑到输出中。 这使得包可以移植到没有.NET安装的机器上,但会将大小膨胀到大约140MB。 Tim选择依赖于框架,因为他使用的每台机器上已经安装了.NET。 如果您分发的工具要给可能没有运行时的同事或客户,自包含是更安全的选择,但对于个人工具,这种权衡很少有意义。
为什么选择WPF而不是MAUI
[2:50 - 4:10] Tim讨论了他收到的关于使用WPF而非MAUI的反馈。 他的理由是实用性而不是意识形态。 图像查看器只需在Windows上运行。 引入MAUI及其跨平台层会增加开销,而对于一个单平台工具并没有任何好处。
除了体系结构的论点外,还有维护的角度。 Tim的原始源代码在大约四五台机器上无重大更改地存活了大约七年。 唯一的更新是框架升级(从.NET Framework到.NET 8,现在到.NET 10)。 如果该实用工具建立在一个需要在苹果或谷歌发布操作系统更新时进行关注的框架上,那么这七年的无需操作将不可能。 一个维护花费的时间比节省的时间还多的实用工具将不再节省您任何时间。
单文件发布和PDB文件
[4:59 - 6:32] 在部署模式确定后,Tim 启用了"生成单文件"并将目标设置为 Windows x64。发布完成并打开输出文件夹,其中包含两个文件:.exe 和 .pdb。
第二个文件是程序数据库文件,其作用值得了解。 当您以Release模式编译时,编译器会优化并重命名内部符号以提高性能。 PDB将这些优化的名称映射回您的实际代码库,使您可以将调试器附加到正在运行的可执行文件,并像在Debug模式下一样设置断点。 对于一个为客户服务的生产应用程序,您应该将PDB文件安全地存储在每次发布旁边,以便在部署后诊断问题。
对于您自己构建的工具,Tim指出PDB不是运行应用程序所需的。 为了简单起见,他删除了它,但警告观众不要养成对用户发布的任何东西这样做的习惯。 单个 .exe 在没有 PDB 的情况下可以自行运行。
值得注意的一个怪事:如果您从依赖框架切换到自包含并保持"单一文件"启用,输出将不再是单文件。额外的运行时文件与可执行文件一起出现。 单文件选项仅在与依赖框架构建配对时生成真正的单文件。
将实用工具放在您的机器上
[7:17 - 7:52] 拿到可执行文件后,Tim将其移至永久位置。 他使用了一个专用的 C:\Apps\SimpleImageViewer 文件夹,这是一个将个人工具与程序文件分开的惯例,方便查找。 来自2024年的可执行文件仍然可以在他当前的机器上运行,这强调了早先关于寿命的观点:设计良好的实用工具与简单项目结构一起,可以在硬件变化和操作系统升级中生存而不被修改。
将工具添加到右键菜单
[7:52 - 10:21] 最后一步是将实用工具接入到Windows资源管理器的上下文菜单中。 Tim修改了Windows注册表,在两个位置添加条目:一个用于右键单击文件夹(以便打开一个图像目录),另一个用于在文件夹内的空白处右键单击(以在当前目录中启动查看器)。
每个注册表条目创建一个shell命令,将选定路径作为命令行参数传递给可执行文件。 这就是应用程序入口点中的 args 参数接收其值的地方。
Tim 提供了一个 .reg 文件,但在共享之前将其重命名为 .txt。 这种预防措施很重要:双击一个 .reg 文件会立即提示将值写入注册表,运行不受信任的注册表文件可能会导致严重的系统问题。 他的做法要求您打开文件、验证路径、更新它们以匹配您的机器、将扩展名改回 .reg,然后才执行它。 如果这些内容听起来有些不熟悉,Tim的建议很直接:不要修改注册表。
对于熟悉注册表的开发者来说,这两个条目是简单明了的。 每个都在适当的键下创建一个命名的 shell 命令,指向您的可执行文件的完整路径,其中包含传递目标目录或文件路径的 %V 或 %1 占位符。可能需要重启才能看到新的上下文菜单条目。
总结:一次部署,永久使用
[10:21 - 10:30] 整个部署过程分两步:发布到文件夹,然后在右键菜单中注册可执行文件。 没有安装程序,没有更新机制,没有云服务。对于您自己机器上的单一用途工具,这种简单就是重点。
结论
[10:30 - 10:40] 总结一下:dotnet publish 使用依赖于框架和单文件设置生成一个轻量级的可执行文件,您可以将其放置在任何地方。 一对注册表条目使其成为Windows资源管理器中可用的上下文菜单操作。
贯穿整个视频的课程是克制。 将您的部署方式与应用程序的范围相匹配。 为个人使用构建的实用工具不需要与产品发售给成千上万客户相同的基础设施,这样对待它只会产生维护工作,侵蚀工具本应节省的时间。
示例提示:即使是个人项目,也要保留您的PDB文件。 将它们存储在与可执行文件相同的文件夹或附近的存档中。如果工具在几个月后行为异常,拥有PDB可以让您附加Visual Studio并调试发布版本,无需从源代码重新编译。

