我们自己写了安装程序,NeuroSquad 从此会自动更新
安装程序在一天之内从 550 MB 瘦到 96 MB,随后又被从零重写。旧的那个出了什么问题,以及现在的更新如何做到永远不弄坏你手上的这一份。
NeuroSquad 0.1.100 是第一个能自己保持最新的版本。走到这一步,用了不到一天、连发三个版本,也得到了这周最有用的一条教训:安装程序是产品的一部分。它是用户看到的第一个窗口,而它一旦失败,就败在最糟糕的位置——旧版本已经没了,新版本还没到。
从 550 MB 到 96 MB
第一个公开的安装程序有 550 MB。大头是听写模型:解压后约 640 MB,打包进来是为了让语音输入在应用打开的那一刻就能用。可听写是可选功能,为了试一块智能体画布就让所有人把它下载下来,这笔账算错了。
0.1.92 不再打包它。模型改为在你需要时下载——在设置向导的“听写”步骤,或之后在“设置”里——下载一完成,听写就自动启用,无需重启。在此之前,状态栏会显示“听写:请下载模型”,而不是报错。安装程序降到了约 110 MB。
剩下的瘦身来自一个不那么光鲜的地方:到底打包了什么。打包工具会把应用的每一个生产依赖完整复制进去,而桌面应用把整套界面技术栈都列在了那里——组件库、图标集、无障碍工具包——尽管打包器早已把这些编译进了页面。把只有页面才需要的东西移出运行时依赖后,省下了约 70 MB 从来没有被加载过的文件。0.1.94 发布时是 96 MB。
为什么自动生成的安装程序必须下岗
最初的安装程序由打包工具生成,其中有两个问题严重到足以让我们自己动手重写。
第一个:NeuroSquad 明明已经关了,它却提示“NeuroSquad 无法关闭”并拒绝安装。它的检查逻辑是“有没有任何进程从安装文件夹里运行”,而且不报名字。真正在运行的,是智能体卡片里那些终端的控制台宿主进程,应用退出后被遗留了下来。你看不到它们,提示里也不点名,也没有任何可以点的按钮。
第二个更糟:被中断的安装可能留下一个写了一半的应用。有一次的情况是:neurosquad.exe 只有 8 MB(本该是 200 MB),而且 Windows 的应用列表里也没有它的条目,连卸载都无从下手。
新的安装程序
它是一个小巧的 WPF 程序,基于 Windows 10 和 11 自带的 .NET Framework 4.8,所以无需预先安装任何东西。可执行文件本身约 240 KB;应用作为 LZMA 负载附加在它后面,切成 32 MB 的块并行压缩和解压,每个文件都有 CRC-32 校验。构建时只下载一次 C# 编译器,并用固定的 SHA-256 校验;构建机器上同样不需要任何 SDK。
它的不同之处,主要在于对你说实话:
- 每一步都有实时日志,既显示在窗口里,也写进
%TEMP%下的文件,出了问题总有一行字可以指给人看。 - 挡路的进程按名称和 PID 列出,只有在你按下按钮后才会结束它们。不靠猜,也不悄悄强杀。
- 更新从不原地覆盖。新版本解压到旧版本旁边,校验通过、一切就绪后才交换两个文件夹。失败或取消都会让旧版本原封不动。
- 卸载只删除装进来的东西——安装时记录的文件、快捷方式和“应用”列表中的条目。你的数据只有在勾选后才会删除。
有一个细节看不见,却至关重要:“开始”菜单快捷方式必须带有应用的 AppUserModelID。没有它,Windows 就不会投递应用的通知——而“你的智能体在等你”恰恰是整个产品赖以成立的那条通知。
在开发用的机器上测试安装程序是有风险的,所以它为此准备了两个开关。--snapshot 会把每一页渲染成 PNG,三种语言任选。--sandbox 会把快捷方式和“应用”列表条目放进一个文件夹,而不是写进“开始”菜单和注册表,这样安装、更新和卸载都能完整跑一遍,而不碰系统分毫。
会自己安装的更新
有了能安全替换正在运行的副本的安装程序,自动更新才成为可能。NeuroSquad 每次启动时和之后每小时检查一次新版本,在后台下载,并用发布页自己公布的校验和核对 SHA-256。没有校验和,就不安装。
更新不是可选项;你能选的是时机。标题栏里的一个圆环显示下载进度;下载完成后,一个带小圆点的图标让你随时可以更新,另有一个对话框对每个版本只问一次:现在,还是下次启动时。选“现在”,应用会关闭并把工作交给安装程序,安装程序等应用退出后覆盖安装,再启动新版本。下次启动时,如果已知有更新的版本,会在应用打开之前就先装好——如果你处于离线状态,应用尝试三次后放弃,打开你现有的版本。
正在下载 NeuroSquad 0.1.108
0.0 / 99.5 MB
下载完成后,可以立即更新,或在下次启动时更新。
更新测试揪出来的那个 bug
更新流程是实打实测过的:两个构建、一个本地发布源,分别测试启动时更新、应用工作中更新,以及离线状态下用已下载好的更新启动。选“立即更新”后,大约十秒钟新版本就出现在屏幕上。
在那之前,第一次运行失败了——卡在交换文件夹这一步。有东西仍然占着安装文件夹,而且不是应用本身。还是那个曾让旧安装程序犯迷糊的孤儿控制台宿主进程:它是某张卡片终端的子进程,它的工作目录就是安装文件夹,因为应用本身就是从那里启动的。一个进程只要把某个文件夹当作当前目录,就足以让 Windows 无法重命名它。
修复只有一行,放在应用启动的最开头:把工作目录切换到用户主文件夹。子进程会继承它,安装文件夹也就不再是任何进程的当前目录。0.1.108 补上了另一半:从旧版本更新时,如果旧版本遗留的终端仍占着文件夹,安装程序现在会把它们和其他进程一起列出来;如果还有它识别不出的东西占着某个文件——比如一个资源管理器窗口——它会逐个替换文件而不是直接放弃,并且任何一步失败都会把一切恢复原样。
安装程序是应用里唯一一个无法靠下一次更新来修复的部分。它必须在其他一切都没运行的时候做对。
如果你用的是 0.1.94 或更早的版本,请在其上运行一次新的安装程序;之后更新都会自动到来。所有变化见 0.1.100 的更新日志。


