运行时体检

给「三山开物」这类打包了 DSH 运行时的桌面应用做版本体检——查已装版本、查 npm 通道、判断能不能更新,并说清为什么"就地热更新"通常不可行。

三山开物 · 运行时版本体检

结论先行

版本体检只做三件事:读本地版本 → 查发布通道 → 按时间线和版本号一起判断。

不要只看 latest 通道,也不要看到"有新版本"就直接覆盖安装目录——打包应用的运行时通常在 Program Files 下、正被自己使用、且没有回滚通道。

关键事实(实测)

| 项 | 值 |

| --- | --- |

| 应用目录 | C:\Program Files\sanshan-kaiwu |

| 运行时 | resources\runtime(node.exe + node_modules,约 835 MB) |

| 版本文件 | resources\runtime\node_modules\@deepseek-ai\dsh\package.json |

| 数据目录 | %APPDATA%\三山开物\dsh-home(由 Electron 以 DSH_HOME 注入) |

| 日志 | %APPDATA%\三山开物\logs\dsh.log |

| npm 通道接口 | https://registry.npmjs.org/-/package/@deepseek-ai%2Fdsh/dist-tags |

步骤

1. 读本地版本

```powershell

$rt='C:\Program Files\sanshan-kaiwu\resources\runtime'

(Get-Content "$rt\node_modules\@deepseek-ai\dsh\package.json" -Raw | ConvertFrom-Json).version

```

检查点:能打印出 0.2.2-alpha.2 这类版本号;打印不出说明装的是别的产品。

2. 查发布通道(latest / alpha / next 三个 tag,别只看一个)

```powershell

$node="$rt\node.exe"

& $node -e "fetch('https://registry.npmjs.org/-/package/@deepseek-ai%2Fdsh/dist-tags').then(r=>r.json()).then(j=>console.log(JSON.stringify(j)))"

```

再用脚本一次性对照本地版本:

```powershell

node scripts/self-update-check.mjs --root "$rt"

node scripts/self-update-check.mjs --root "$rt" --json # 给 CI / 上层程序用

```

退出码:0 无需更新、2 有可用新版本、1 检查失败。

3. 判断(两个信号一起看)

- 按 semver:0.2.2-alpha.2 大于 0.2.1-rc.5(0.2.2 > 0.2.1)。

- 按发布时间:0.2.1-rc.5(10-30)晚于 0.2.2-alpha.2(10-28),属于稳定线的新修复。

- 结论写法:当前在 alpha 线最新;稳定线发布更晚但版本号更低、缺少 alpha 新功能。只说"版本号最高"或只说"发布时间最新"都是错的。

为什么不能就地热更新(四道锁)

| 锁 | 实测 | 后果 |

| --- | --- | --- |

| 目录只读 | 在 resources\runtime 建探测文件返回 Access denied(进程未提权) | 需要 UAC / 安装器 |

| 正在运行 | dsh web 加载的就是这份运行时,端口由启动日志给出 | 替换即中断会话,无法自检 |

| 无回滚通道 | dist 里没有 latest.yml,无签名、无备份目录 | 失败只能整包重装 |

| 运行时无 npm | runtime 里只有 node.exe 与 node_modules | 机内无法解析新依赖树,只能整包重建 |

安全更新路线

1. 构建机改 runtime/package.json → npm install → npm run dist:win → npm run smoke。

2. 签名 → 发布安装包 + SHA-256 + 更新说明。

3. 用户托盘「退出」→ 装新包(UAC)→ 启动后核对版本。

4. 回滚:重装上一版安装包,dsh-home 数据不动。

验收清单

别做的事