Skip to content

自动更新

HMX平台内置了文件自动更新服务,支持后端服务和前端WinForm客户端的自动更新。

更新策略

文件对比策略

对比项说明
FullName文件相对路径
LastWriteTime文件最后修改时间
Md5Hash文件MD5校验值

更新判断逻辑:

  1. 远程有、本地无 → 下载(新增)
  2. 远程有、本地有但MD5不同 → 下载(更新)
  3. 本地有、远程无 → 重命名为.delete(删除)

文件保护机制

以下文件不会被自动删除:

保护类型规则
调试模式Debugger.IsAttached 时跳过删除
卸载程序unins*.exeunins*.dat
配置文件.json.xml.cfg.config.db
系统目录logsconfigbackups

下载策略

配置说明
并发数3同时下载的最大文件数
重试次数3下载失败后自动重试
轮询间隔5分钟服务端文件夹监控间隔

服务端配置

启用自动更新服务

Program.cs 中添加:

csharp
var app = builder.Build();

app.UseAutoUpdateServer();  // 启用自动更新服务

app.Run();

API接口

接口方法说明
/autoupdate/indexGET获取更新文件列表(JSON)
/autoupdate/downloadGET下载单个文件,参数:filename
/autoupdate/latest-full.zipGET下载完整更新包(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)
    {
        // 执行更新逻辑
    }
}

发布流程

手动发布

  1. 在开发环境执行 Publish
  2. 将发布文件复制到服务器的 update 文件夹
  3. 服务端自动监控文件夹变化,生成文件列表
  4. 客户端下次启动时检测到更新

自动发布(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
   │              │    └─ 新文件 → 正式文件
   │              │
   │              └─ 更新完成 → 重启程序

常见问题

客户端无法检测更新

排查步骤:

  1. 确认 autoupdateUrl 配置正确
  2. 确认更新服务器已启用 UseAutoUpdateServer()
  3. 访问 http://server:port/autoupdate/index 测试接口

更新后程序无法启动

可能原因:

  1. 关键配置文件被覆盖
  2. 依赖的DLL版本不兼容

解决方案:

  • 配置文件(.json、.xml等)默认受保护,不会被自动删除
  • 检查 backups 目录中的 .delete 文件,可手动恢复

如何回滚更新

更新后的旧文件保存在 backups 目录(.delete 后缀):

backups/
├── YourApp.dll.250101120000.1234.delete
└── ...

重命名回原文件名即可恢复。

HiMind 工业互联网平台 技术文档