探秘Upgrade.Net:你的.NET项目自动化升级利器
一个精心设计的自动化升级方案,比你想象的重要得多。
作为一名 .NET 开发者,你一定经历过这样的场景:产品迭代了十几个版本,每次都要手动打包、发给客户、远程指导覆盖文件、解压、替换,稍有不慎就搞出生产事故来。客户在群里一阵狂轰滥炸,你只能一边道歉一边排查。
更别提当你面对的是数十个甚至上百个客户端时,那简直就是运维的噩梦。
Upgrade.Net 正是为终结这种痛苦而生的一款轻量级开源组件。今天我们就来深入拆解它,看看这个基于 .NET 10 打造的自动化升级方案,是如何将复杂的升级流程化繁为简的。
一、Upgrade.Net 是什么?
Upgrade.Net 是一个基于 .NET 的 Windows 应用自动化升级解决方案,采用 MIT 开源协议,目前托管在 Gitee 上。
它不是那种"大而全"的庞然大物,而是精准聚焦在一个痛点场景:让你的桌面应用能够自动从远程服务器下载更新包,解压、备份、替换文件,然后无缝启动新版本。
讲得直白一点——你的客户端应用集成了它之后,升级这件事基本就不再需要人工介入了。
核心设计理念
Upgrade.Net 的聪明之处在于,它把升级这件事抽象成了「步骤 + 操作」的模型:
- 步骤(Step):升级流程中的一个个节点,比如"下载更新包"、"备份旧文件"、"解压覆盖"。
- 操作(Option):每个步骤具体执行的动作,共计 16 种内置操作类型。
你只需要写一个 JSON 配置文件,定义好步骤序列,剩下的全部交给引擎自动执行。这种声明式的配置方式,意味着不需要改一行代码就能调整升级流程。
二、架构拆解:三大模块各司其职
Upgrade.Net 采用了教科书级别的模块化设计,整个项目被拆成三个独立组件:
Upgrade.Net.slnx
├── Upgrade.Net/ # 核心类库
├── Upgrade.Cmd/ # 控制台版本
└── Upgrade.Wpf/ # WPF 桌面版本
2.1 Upgrade.Net — 核心引擎
这是整个项目的灵魂。它负责:
- 配置解析:读取 JSON 配置文件,反序列化为
StepConfig对象数组; - 策略执行:每个步骤根据
Option字段创建对应的UpgradeAction,采用策略模式调度; - 状态管理:通过
UpgradeView接口向外层(控制台或 WPF)推送执行状态; - 异常处理:内置重试机制、
continueOnError容错开关、自定义等待时间。
一套核心引擎同时驱动两套完全不同的 UI 界面,靠的就是 UpgradeView 这个接口的抽象能力——这在对设计模式的应用上是相当干净的。
2.2 Upgrade.Cmd — 控制台版
适合集成到 CI/CD 流水线、后台静默升级、或者不需要图形界面的轻量场景。执行一个命令,升级过程自动跑完,终端输出完整日志。
2.3 Upgrade.Wpf — 桌面版
面向最终用户的图形界面方案。采用了 MVVM 架构,无边框窗口设计搭配中国蓝主题,颜值在线。支持:
- 实时进度条和状态信息展示;
- 下载的暂停 / 继续 / 取消交互;
- 升级步骤可视化列表;
- 版本更新日志滚动展示。
两个 UI 版本共享同一套核心逻辑,这种「一个引擎,两套壳」的设计,对于需要同时覆盖技术用户和普通用户的团队来说,非常务实。
三、界面一览:两种风格,同样优雅
说再多不如眼见为实。来看看 Upgrade.Net 实际运行时的样子。
WPF 桌面版
WPF 版本采用了无边框窗口 + 中国蓝主题的设计语言,界面简洁大方,适合面向终端用户的场景。
开始界面 — 清晰的标题、版本信息和步骤概览,让用户一眼就知道即将发生什么:

升级进行中 — 实时进度条、当前步骤高亮、状态标签一目了然,支持暂停/继续/取消:

升级完成 — 所有步骤打上勾,提示即将启动新版本,体验闭环:

控制台版
控制台版本则走极简路线,终端信息密度高,适合集成到自动化流水线或服务器后台场景。
开始界面 — 纯文本版升级信息,附带 ASCII 进度条:

升级进行中 — 每个步骤的执行状态实时输出,日志清晰可追溯:

升级完成 — 全部步骤通过,自动退出:

两种界面风格覆盖了从「普通用户」到「运维人员」的全场景,选哪个完全取决于你的目标受众。
四、16 种操作类型:一个配置搞定一切
这是 Upgrade.Net 最让我眼前一亮的设计。它把升级过程中可能用到的所有原子操作拆成了 16 种内置类型:
| 操作类型 | 用途 | 典型场景 |
|---|---|---|
Download |
从 URL 下载文件 | 拉取远程更新包 |
Command |
执行命令行(同步等待) | 执行数据库迁移脚本 |
Launch |
启动外部程序(异步) | 升级后启动主程序 |
Zip |
压缩文件/目录 | 生成日志归档 |
Unzip |
解压文件 | 解压更新包 |
MoveDir / MoveDoc |
移动目录/文件 | 迁移旧数据 |
CopyDir / CopyDoc |
复制目录/文件 | 复制配置文件 |
CreateDir / CreateDoc |
创建目录/文件 | 创建运行时需要的目录 |
DeleteDir / DeleteDoc |
删除目录/文件 | 清理临时文件 |
RenameDir / RenameDoc |
更名目录/文件 | 备份旧版本 |
几乎覆盖了应用升级中你能想到的所有文件系统操作。每一个步骤还可以独立配置:
waitTime:执行后等待时间,支持倒计时显示——比如"更新将在 5 秒后重启";retryCount+retryDelay:重试次数和延迟——网络抖动?自动重试;continueOnError:失败是否继续——非关键步骤出错不阻断整体流程。
这种颗粒度的掌控力,让你可以像搭积木一样自由编排升级流程,而不是被框架的固定流程框死。
五、配置文件:声明式编排的艺术
来看看一个典型的升级配置长什么样:
{
"icon": "logo.ico",
"title": "MyApp 升级程序",
"oldVersion": "1.0.0",
"newVersion": "2.0.0",
"autoStart": true,
"autoClose": true,
"showSteps": true,
"verInfo": "本次更新:\n- 修复了数据导出 Bug\n- 新增报表模块\n- 优化内存占用",
"steps": [
{
"title": "下载更新包",
"description": "正在从服务器获取最新版本...",
"option": "Download",
"url": "https://cdn.example.com/releases/v2.0.0.zip",
"file": "update.zip",
"retryCount": 3,
"retryDelay": 2000
},
{
"title": "备份当前版本",
"description": "正在备份现有文件以防意外...",
"option": "CopyDir",
"source": "./app",
"destination": "./backup/1.0.0"
},
{
"title": "解压更新包",
"description": "正在解压新版本文件...",
"option": "Unzip",
"source": "update.zip",
"destination": "./app",
"overwrite": true
},
{
"title": "清理安装包",
"description": "正在清理临时文件...",
"option": "DeleteDoc",
"path": "update.zip"
},
{
"title": "启动新版本",
"description": "即将启动 MyApp v2.0.0",
"option": "Launch",
"command": "dotnet",
"args": "MyApp.dll",
"path": "./app",
"waitTime": 3
}
]
}
配置即文档——任何一个运维人员甚至客户自己,不需要懂 C#,打开 JSON 文件就能看懂升级流程在干什么。这种声明式配置带来的可维护性提升,远胜于把流程硬编码在代码里。
六、技术栈解析:做了哪些正确的选择
5.1 .NET 10 — 激进的版本策略
Upgrade.Net 直接上了 .NET 10.0,这在当下的 .NET 生态中属于相当激进的选择。带来的好处是:原生 AOT 编译的潜力、JsonSerializer 源生成器的极致性能、以及跨平台能力的基础支撑。
5.2 HttpClient 静态复用
核心类库中对 HttpClient 采用的是静态单例复用而非每次 new——这是处理网络请求的经典最佳实践。如果你曾经被 TIME_WAIT 端口耗尽问题折磨过,会明白这个细节有多重要。
5.3 策略模式 + MVVM
设计模式上,操作执行采用了策略模式——每个 UpgradeOption 枚举值对应一个具体的 UpgradeAction 子类,扩展新操作只需新增枚举和实现类即可,完全符合开闭原则。UI 层则是标准的 MVVM 分离,View 和 ViewModel 通过接口解耦,可测试性和可维护性都有保障。
5.4 Windows 7+ 兼容
更难得的是,项目明确声明了支持 Windows 7 及以上系统。很多现代化开源工具默认放弃了对 Win7 的兼容,但对于仍有大量 Win7 客户的 toB 软件来说,这个细节意味着你可以放心地集成 Upgrade.Net 而不必担心客户端的系统版本问题。
七、实战集成:三步让你的应用具备自升级能力
第一步:引入 Upgrade.Net 核心库
克隆仓库或将核心类库添加到你的解决方案中。如果你的主程序已经是一个 .NET 项目,集成几乎零成本——直接项目引用即可。
第二步:编写升级配置文件
参照上面的配置示例,根据你的项目实际情况编写 upgrade.json:
- 设置图标、标题、版本信息;
- 编排步骤序列——下载 → 备份 → 解压 → 启动是标准四步;
- 根据网络环境调整重试参数。
第三步:在你的主程序中触发升级
在你应用的"检查更新"入口处,启动 Upgrade.Cmd 或 Upgrade.Wpf:
// 简单粗暴的方式:直接拉起升级程序
Process.Start("Upgrade.Wpf.exe");
// 然后退出当前进程
Application.Current.Shutdown();
剩下的——下载、备份、解压、覆盖、重启——全部由 Upgrade.Net 自动完成。
八、值得关注的细节与使用建议
在使用过程中,有几个经验点值得留意:
-
升级程序与主程序分离执行。这是基本原则——升级器必须独立于被升级的程序运行,否则你无法覆盖正在使用的文件。Upgrade.Net 把这个理念贯穿到了设计里。
-
充分利用备份机制。强烈建议在任何覆盖操作之前先
CopyDir备份当前版本。多写一步配置,省去一万次回滚的麻烦。 -
控制台版适合 CI/CD 集成。如果你有自己的构建流水线,可以把 Upgrade.Cmd 集成进去,实现"构建完自动推送到客户端并触发升级"的闭环。
-
WPF 版的交互设计值得参考。暂停/继续/取消的下载交互、步骤状态的四色标识(等待/执行中/完成/失败),这些细节让用户对升级进度一目了然,不再是看着一根进度条尬等。
-
continueOnError的使用要审慎。非关键步骤(如清理临时文件)可以设为true以防阻塞流程,但关键步骤(如文件覆盖)务必让其失败时中断,避免产生半升级的不一致状态。
九、总结
在.NET 桌面应用开发中,自动升级能力往往是最容易被低估的功能——直到你真正需要它的时候,才发现自己缺了一条腿。
Upgrade.Net 的价值不在于它用了多么高深的技术,而在于它用简洁的设计覆盖了真实场景中最繁琐的那部分工作。16 种原子操作覆盖了文件系统操作的全集,策略模式保证了扩展性,JSON 配置实现了零代码编排,两套 UI 适配了不同用户群体——每一处设计都直击痛点。
对于那些需要向客户分发桌面客户端的 .NET 团队来说,Upgrade.Net 几乎是一个开箱即用的升级基础设施。花半小时配好一份 upgrade.json,从此告别手动拷贝文件的运维噩梦。
开源地址:https://gitee.com/leadiot/upgrade.net
如果你觉得它有用,不妨给作者点个 Star,你的每一次认可,都是开源社区持续进步的动力。

浙公网安备 33010602011771号