以前点「发现新版本」,只会弹一句“是否打开下载页”——浏览器跳走,用户还得自己记着下载、解压、找旧 exe 覆盖。把“检查更新”做成了“提醒更新”,最后一步始终卡在手动操作上。

v1.4.0 把这一步补完:客户端可以在程序内下载更新包、校验、退出、替换并自动重启,全程不用打开浏览器。同时把上一版(1.3.1)已完成的 JASS 注入配置交付能力一起带上——1.3.1 没有单独发版,本次一并发布。

这次更新了什么

1. 程序内自动更新(本次核心)

发现新版本时会弹出三个选择:自动更新 / 打开下载页 / 稍后。

选择自动更新后:

  • 工具在后台流式下载 ZIP 更新包,进度窗口显示已下载字节数与百分比,可随时取消;
  • 下载完成后按服务端给出的 SHA-256 与字节数双重校验,不一致直接丢弃,不会装上一个损坏的包;
  • 只从包内解出唯一一个 exe,拒绝路径穿越、拒绝非 Windows 程序文件、限制包与 exe 体积;
  • 解出的新版本以 --apply-update 模式自举为替换进程,等旧进程完全退出后:先把旧 exe 备份为 .exe.bak,再覆盖写入并启动新版本。

失败不会留下半截状态:

  • 任一步校验失败、下载中断、替换时文件被占用,都会还原旧 exe 并提示是否改为打开下载页;
  • .exe.bak 保留 7 天,新版本确认可用后自动清理,避免 36 MB 残包长期堆积;
  • 服务端未配置哈希、或当前不是打包后的 exe(源码运行)时,自动退回“打开下载页”,行为与 1.3.x 一致。

2. 服务端新增更新包校验字段

/admin/download 管理页新增两项:更新包 SHA-256 与更新包字节数。

  • 两项可以留空,留空即维持旧行为(只打开下载页);
  • 填了就启用程序内更新,客户端会强校验;两项必须同时填写,格式错误会被服务端拒绝;
  • 公开接口 /api/download 只多返回这两个字段,仍不涉及任何上传数据;
  • 下线下载入口时,两个字段一并清空。

3. 分发改用 ZIP 更新包

自动更新需要解压,而用户机器上不一定装了 WinRAR。因此安装包改以 ZIP 分发(Python 内置解压,不依赖第三方工具)。RAR 版本仍可继续提供,只是走自动更新的用户需要 ZIP。

4. 一并带上 1.3.1 的 JASS 注入增强

1.3.1 当时未单独发版,内容合并到本版:

  • 「导出配置 / 导入配置」:把调好的注入步骤存成 JSON 发给其他作者,导入时先命名、同名可覆盖,兼容旧版字段,且不含地图路径;
  • Markdown 报告改为「步骤总览 + 分步详情」,批量命中压成一行;
  • 应用成功后自动回到步骤详情并清空旧 diff,保留当前步骤选中;
  • 服务端实时诊断流的长文本按换行展示。

怎么升级

第一次升级到 1.4.0 仍需手动一次(旧版本没有自更新能力):

  1. 先更新服务端(含 sha256 / size 字段),否则客户端仍只会打开下载页;
  2. 退出正在运行的工具;
  3. 用 v1.4.0 的 exe 覆盖旧版 exe;
  4. 保留同目录的 analyzer_config.json、history.db 与 jass_inject/ 目录。

从 1.4.0 起,后续版本就可以直接点「自动更新」完成升级。

验证说明

  • 全量回归 402 项通过(2 项跳过、2 项预期失败),新增 27 项自更新相关用例:哈希/字节数校验、取消下载、HTTP 失败、路径穿越、多 exe、非 PE 文件、替换成功、替换失败回滚、旧进程不退出、备份保留与过期清理;
  • 端到端冒烟:本地 HTTP 提供真实 ZIP,真实 1.4.0 exe 完成「下载 → 校验 → 解压 → helper 替换 → 重启」,.bak 内容为旧版本,退出码 0;
  • GUI 冒烟:主循环驱动更新进度窗口走完整流程,确认替换成功且只触发一次退出。

下载与反馈

安装包与更新说明见下载页:
https://ca.darksheep.vip/download

遇到问题时,可以在「崩溃诊断」页上传日志获得 6 位上传码,把上传码发给维护者或地图作者。

隐私与数据边界

  • 更新过程只下载更新包,不上传任何本机数据;
  • 校验在本地完成,不上报下载结果或本机信息;
  • 下载的更新包放在系统临时目录,成功替换后由下次启动清理;
  • 其余数据范围与 1.3.x 相同,未新增任何采集项。

——萧夜