探秘Upgrade.Net:让更多的项目支持自我升级

0 阅读5分钟

全面支持.Net Standard 2.0 标准,从 .NET Framework 老项目到 .NET 10 新工程,统统能接上。


引子

每个写过 .NET 桌面端的工程师,几乎都踩过同一个坑:升级。

客户机器散落全国,系统从 Win7 到 Win11,运行时从 .NET Framework 4.6 到 .NET 10。你发布一个新版本,就要远程指导用户手动拷贝、解压、替换——祈祷不出岔子。

Upgrade.Net 是为终结这件事而生的开源组件。它真正值得说道的地方不是“能升级”,而是用一套核心库,吃下整个 .NET 生态——核心库直接打通 netstandard2.0,十年前的老工程和刚上 .NET 10 的新项目,都可以零成本接进来。


一、.NET Standard 2.0:一库适配所有 .NET 生态

打开 Upgrade.Net/Upgrade.Net.csproj,第一行就是答案:

<TargetFramework>netstandard2.0</TargetFramework>

.NET Standard 2.0 是一套 API 契约,不是运行时。任何兼容它的运行时都能直接引用编译好的 dll:

运行时最低版本场景
.NET Framework4.6.1+WinForm/WPF 老项目
.NET Core / .NET 5~10全部现代跨平台桌面/服务
Mono / Xamarin / Unity5.4+第三方运行时 & 游戏引擎

翻译成业务语言:客户机器装的是什么版本不重要,只要 ≥ .NET Framework 4.6.1,你的升级器就能跑。对 toB 软件厂商来说,这是比任何花哨特性都重要的能力。


二、目标框架支持矩阵:七大框架同时编译

只有核心库兼容不够。Upgrade.Net 把控制台版(Upgrade.Cmd)和 WPF 版(Upgrade.Wpf)都做了多目标编译——同一个项目同时产出 7 个框架的可执行文件:

<!-- Upgrade.Cmd.csproj -->
<TargetFrameworks>net472;net48;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
<!-- Upgrade.Wpf.csproj -->
<TargetFrameworks>net472-windows;net48-windows;net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows;net10.0-windows</TargetFrameworks>

合并后覆盖矩阵:

框架CmdWpf典型场景
.NET Framework 4.7.2政企老服务器、Win7/8.1
.NET Framework 4.8Win10/11 默认运行时
.NET 6.0 / 8.0 (LTS)跨平台桌面、长期支持
.NET 7.0 / 9.0 / 10.0最新 STS / 跟进最新

全部框架 0 警告 0 错误 通过编译验证(见 DOCS/兼容性分析.md)。

一句话:从 Win7 工控机到 .NET 10 新工程,全程在线。


三、界面一览

在聊代码前,先眼见为实。Upgrade.Net 提供控制台和 WPF 两套界面,共享同一套核心逻辑,通过 UpgradeView 接口驱动。

WPF 桌面版

适合面向终端用户的客户端应用,标题、版本号、步骤清单、进度条一应俱全。

开始界面 — 标题、版本对比、当前步骤清单一目了然:

WPF 开始界面

升级进行中 — 当前步骤高亮,已完成步骤打勾,支持等待倒计时:

WPF 升级界面

进度详情 — 步骤面板下方追加进度条,按钮变为"升级中…":

WPF 进度界面

升级完成 — 所有步骤全部成功,提示用户退出:

WPF 完成界面

控制台版

适合服务器、CI/CD、无人值守等无 GUI 场景,纯文本风格。

开始界面 — ASCII 风格,显示版本信息和步骤清单:

控制台开始界面

升级进行中 — 终端日志按步骤滚动输出,含倒计时和重试提示:

控制台升级界面

升级完成 — 全部通过,给出"所有升级步骤执行完成"的总结:

控制台完成界面


四、16 种原子操作:覆盖升级全集

Upgrade.Net 把升级中用到的所有文件/进程操作拆成了 16 种功能性子操作,每种都是独立的 StepConfig

分类操作
网络Download(下载)、Upload(上传)
进程Command(同步执行命令行)、Launch(异步启动程序)
压缩Zip(压缩)、Unzip(解压)
目录MoveDir、CopyDir、CreateDir、DeleteDir、RenameDir
文件MoveDoc、CopyDoc、CreateDoc、DeleteDoc、RenameDoc

每个步骤还支持:

  • waitTime:执行后等待 + 倒计时显示("应用将在 5 秒后重启")
  • retryCount + retryDelay:失败自动重试,应对网络抖动
  • continueOnError:非关键步骤失败不阻断流程

像搭积木一样编排升级流程,不需要改一行 C# 代码


五、升级流程代码示例

5.1 一份 JSON 搞定完整升级

下面是覆盖“下载 → 备份 → 解压 → 清理 → 启动”的完整配置:

{
  "title": "MyApp 升级程序",
  "oldVersion": "1.0.0",
  "newVersion": "2.0.0",
  "autoStart": true,
  "autoClose": true,
  "verInfo": "本次更新:\n- 修复已知 Bug\n- 新增报表模块",
  "steps": [
    {
      "title": "下载更新包",
      "option": "Download",
      "url": "https://cdn.example.com/releases/v2.0.0.zip",
      "file": "update.zip",
      "retryCount": 3,
      "retryDelay": 2000
    },
    {
      "title": "备份当前版本",
      "option": "CopyDir",
      "source": "./app",
      "destination": "./backup/1.0.0"
    },
    {
      "title": "解压覆盖",
      "option": "Unzip",
      "source": "update.zip",
      "destination": "./app",
      "overwrite": true
    },
    {
      "title": "清理安装包",
      "option": "DeleteDoc",
      "path": "update.zip"
    },
    {
      "title": "启动新版本",
      "option": "Launch",
      "command": "dotnet",
      "args": "MyApp.dll",
      "path": "./app",
      "waitTime": 3
    }
  ]
}

5.2 在 WPF 主程序中触发升级

核心库 netstandard2.0,.NET Framework 4.7.2 到 .NET 10 的引用方式完全一致:

using Com.Scm.Upgrade;
using Com.Scm.Upgrade.Config;

public partial class MainWindow : Window, UpgradeView
{
    private async void CheckUpdate_Click(object sender, RoutedEventArgs e)
    {
        // 加载 JSON 配置
        var config = UpgradeConfig.Load();
        // 也可以用代码动态构造(从服务器拉版本信息时更灵活)
        // config = new UpgradeConfig { ... };
        // config.Steps = new List<StepConfig> {
        //     StepConfig.NewDownloadStep("下载", "https://...", "update.zip"),
        //     StepConfig.NewUnzipStep("解压", "update.zip", "./", overwrite: true),
        //     StepConfig.NewLaunchStep("启动", "MyApp.exe", "./")
        // };

        var upgrade = new Upgrade(this);       // Window 实现 UpgradeView
        await upgrade.StartAsync(config);      // 异步执行,UI 实时同步进度
        Application.Current.Shutdown();        // 升级结束退出
    }
}

UpgradeView 接口提供 Log / LogStep / LogStepStatus / LogStepProgress 等方法,你在 WPF 里绑定到 TextBox、ProgressBar 即可;控制台版换成 Console.WriteLine 即可。

5.3 跨框架集成速查

场景方式备注
NuGet 引用dotnet add package Com.Scm.Upgrade推荐。需额外引入 Newtonsoft.Json(≥13.0)
源码引用<ProjectReference Include="..\Upgrade.Net\Upgrade.Net.csproj" />适合需要魔改流程
.NET Framework 老项目同上,Process.Start("Upgrade.Cmd.exe")默认不带 Newtonsoft.Json,手动加


六、总结

Upgrade.Net 不是又一个“造轮子”的玩具,而是认真考虑过真实落地场景的工程方案:

一个 netstandard2.0 类库,覆盖 .NET Framework 4.7.2 ~ .NET 10 全谱系;一份 JSON 配置,编排从下载到启动的全套流程;两套 UI(控制台 + WPF),适配服务器到终端用户的全场景。

对于需要向客户分发桌面客户端的 .NET 团队:

  • 不用为每个运行时维护一套升级器

  • 新功能只需改 JSON,不动代码

  • 重试、等待、错误处理内置

  • WPF 版带暂停/继续/取消,比手写进度条靠谱得多

  • 项目地址(NuGet):Com.Scm.Upgrade

  • 源码仓库:github.com/leadiot/Upg…

  • 当前版本:1.2.4(2026-07-27)

如果觉得有用,欢迎给项目点个 Star ⭐。