自动更新
HMX平台内置了文件自动更新服务,支持后端服务和前端WinForm客户端的自动更新。
更新策略
文件对比策略
| 对比项 | 说明 |
|---|---|
| FullName | 文件相对路径 |
| LastWriteTime | 文件最后修改时间 |
| Md5Hash | 文件MD5校验值 |
更新判断逻辑:
- 远程有、本地无 → 下载(新增)
- 远程有、本地有但MD5不同 → 下载(更新)
- 本地有、远程无 → 重命名为.delete(删除)
文件保护机制
以下文件不会被自动删除:
| 保护类型 | 规则 |
|---|---|
| 调试模式 | Debugger.IsAttached 时跳过删除 |
| 卸载程序 | unins*.exe、unins*.dat |
| 配置文件 | .json、.xml、.cfg、.config、.db |
| 系统目录 | logs、config、backups |
下载策略
| 配置 | 值 | 说明 |
|---|---|---|
| 并发数 | 3 | 同时下载的最大文件数 |
| 重试次数 | 3 | 下载失败后自动重试 |
| 轮询间隔 | 5分钟 | 服务端文件夹监控间隔 |
服务端配置
启用自动更新服务
在 Program.cs 中添加:
csharp
var app = builder.Build();
app.UseAutoUpdateServer(); // 启用自动更新服务
app.Run();API接口
| 接口 | 方法 | 说明 |
|---|---|---|
/autoupdate/index | GET | 获取更新文件列表(JSON) |
/autoupdate/download | GET | 下载单个文件,参数:filename |
/autoupdate/latest-full.zip | GET | 下载完整更新包(ZIP) |
文件夹结构
应用程序目录/
├── update/ # 更新文件目录(服务端监控此目录)
│ ├── bin/
│ │ └── YourApp.dll
│ └── ...
├── wwwroot/
│ └── latest-full.zip # 自动生成的完整包
├── appsettings.json
└── YourApp.exe服务端配置示例
json
{
"Urls": "http://0.0.0.0:5225"
}注意:自动更新服务端口与主服务相同,无需额外配置端口。
客户端配置
配置文件格式
自动更新客户端使用 *.exe.config 文件配置更新服务器地址(传统.NET Framework格式):
xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="autoupdateUrl" value="http://10.11.5.57:5225"/>
<add key="autoUpdateMainExe" value="Hmx.Winforms.Startup.exe"/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>| 配置项 | 说明 |
|---|---|
autoupdateUrl | 更新服务器地址(后端服务地址) |
autoUpdateMainExe | 更新完成后启动的主程序 |
注意:配置文件必须放在应用程序运行目录,文件名格式为
{程序名}.exe.config。
客户端使用
检测更新
csharp
var client = new AutoUpdateClient();
var processor = client.CheckUpdate();
if (processor.NeedUpdate)
{
Console.WriteLine($"发现 {processor.UpdateFiles.Count} 个文件需要更新");
// 执行更新
await processor.StartUpdateAsync();
Console.WriteLine("更新完成");
}
else
{
Console.WriteLine("已是最新版本");
}监听更新进度
csharp
processor.ProgressChanged += (sender, args) =>
{
Console.WriteLine($"[{args.Progress}%] {args.Message}");
};启动时检查更新
csharp
// WinForm启动时检查
if (AutoUpdateNotify.CheckNeedUpdate())
{
var result = MessageBox.Show("检测到新版本,是否立即更新?", "更新提示",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
// 执行更新逻辑
}
}发布流程
手动发布
- 在开发环境执行 Publish
- 将发布文件复制到服务器的
update文件夹 - 服务端自动监控文件夹变化,生成文件列表
- 客户端下次启动时检测到更新
自动发布(DevOps)
yaml
# azure-pipelines.yml 示例
- task: CopyFiles@2
displayName: '复制更新文件'
inputs:
SourceFolder: '$(Build.SourcesDirectory)\output\publish'
Contents: '**'
TargetFolder: '\\server\share\update'更新流程详解
1. 客户端启动
│
├─ 读取配置获取更新服务器地址
│
├─ 请求 /autoupdate/index 获取远程文件列表
│
├─ 扫描本地文件,生成本地文件列表
│
├─ 对比差异(MD5校验)
│
├─ 返回 AutoUpdateProcessor
│ │
│ ├─ NeedUpdate = false → 正常启动
│ │
│ └─ NeedUpdate = true → 显示更新提示
│ │
│ └─ 执行 StartUpdateAsync()
│ │
│ ├─ 并发下载文件(最多3个)
│ │
│ ├─ 下载完成 → 重命名文件
│ │ ├─ 旧文件 → *.delete
│ │ └─ 新文件 → 正式文件
│ │
│ └─ 更新完成 → 重启程序常见问题
客户端无法检测更新
排查步骤:
- 确认
autoupdateUrl配置正确 - 确认更新服务器已启用
UseAutoUpdateServer() - 访问
http://server:port/autoupdate/index测试接口
更新后程序无法启动
可能原因:
- 关键配置文件被覆盖
- 依赖的DLL版本不兼容
解决方案:
- 配置文件(.json、.xml等)默认受保护,不会被自动删除
- 检查
backups目录中的.delete文件,可手动恢复
如何回滚更新
更新后的旧文件保存在 backups 目录(.delete 后缀):
backups/
├── YourApp.dll.250101120000.1234.delete
└── ...重命名回原文件名即可恢复。