DSH / Atlas
2026-09-11implementedarchitecturearchived 2026-09-30

Replace Windows application directories after staging

暂存完成后替换 Windows 应用目录

The Desktop distribution contains thousands of small files. Extracting to the temporary directory, copying every file to the installation, and deleting the temporary tree repeats filesystem work. A 616,701,792-byte, 11,735-file payload took 101.235, 79.203, and 114.391 seconds through those three phases on Windows; copying accounted for 70.296, 56.688, and 85.281 seconds. These component measurements exclude old-vers

English

Problem

The Desktop distribution contains thousands of small files. Extracting to the temporary directory, copying every file to the installation, and deleting the temporary tree repeats filesystem work. A 616,701,792-byte, 11,735-file payload took 101.235, 79.203, and 114.391 seconds through those three phases on Windows; copying accounted for 70.296, 56.688, and 85.281 seconds. These component measurements exclude old-version removal, registration, startup, and cache clearing.

Decision

The NSIS adapter retains electron-builder's installer, signed uninstaller generation, registration, shortcuts, and updater cache. It stages the complete new application beside the destination before stopping the old application. The directory transaction renames the old directory to a unique backup, renames the new directory to the destination, and removes the backup before launch. Both renames stay on the destination volume. This replaces the copy-based installation decision in the packaging note.

The installer embeds its pinned 7-Zip command-line tool, signs its private copy for signed releases, and includes its license texts. Windows records the copied runtime inventory after its executable resources have been signed. A nonzero extraction exit leaves the old application intact. Explicit cleanup before upstream installer exits also covers silent cancellation. Same-path upgrades bypass the old uninstaller so it cannot delete the rollback copy or registration prematurely. Different-path and installation-scope migrations retain electron-builder's old-uninstaller behavior; the directory rollback does not undo those uninstall operations.

Consequences

Directory cleanup, including uninstallation, uses extended-length Windows paths for deeply nested dependencies and backup suffixes. Failed promotion attempts restore the renamed old directory. If another process prevents restoration, the complete backup remains available. Abrupt process termination or power loss can leave staging or backup directories; the installer does not claim crash-atomic replacement across two renames. The transaction changes installation files, not the external Desktop plugin profile or product data.

Alternatives considered

  • Direct extraction over the running installation. The existing locked-file probe demonstrates that Nsis7z::Extract can retain an old file without setting the NSIS error flag. Staging through a tool with an exit status avoids accepting a mixed installation.
  • Delete the old version before extraction. A corrupt archive or failed write would remove the only usable version before replacement is ready.
  • Put the Host in ASAR. Native modules, package resolution, and subprocess paths require separate qualification; directory replacement preserves the resource layout.

Verification

The native directory smoke calls production macros against private directories. It covers fresh installation, obsolete-file removal on upgrade, locked-directory failure, restoration after the second rename fails, corrupt archives, and cancellation cleanup. Template tests pin staging before shutdown and promotion before registration. The signed 0.1.5-rc.2 installer passed fresh installation, same-path upgrade with obsolete-file removal, locked-file failure preserving the old installation, installation-location migration, and complete uninstallation on Windows. Each installation check compared all 11,736 payload files against the packaged tree and verified executable/uninstaller signatures and registration. The installed runtime passed native dependency, Web frontend, external plugin route, and actual Electron window startup/exit checks. The final installer sample took 38.0 seconds for fresh installation and 27.5 seconds for same-path upgrade, excluding verification and launch; caches were not cleared. These are full-installer observations, separate from the component baseline above. Hosted updater download and upgrades from historical published releases remain release qualification.

中文

问题

Desktop 分发包包含数千个小文件。先解压到临时目录,再将每个文件复制到安装位置,最后删除临时树,会重复执行文件系统操作。Windows 上一份 616,701,792 字节、11,735 个文件的载荷经过这三个阶段分别耗时 101.235、79.203 和 114.391 秒,其中复制占 70.296、56.688 和 85.281 秒。这些组件测量不包括旧版卸载、注册、启动,也没有清空缓存。

决策

NSIS 适配器保留 electron-builder 的安装器、签名卸载器生成、注册、快捷方式和更新缓存。它在停止旧应用前,将完整新应用暂存到目标目录旁。目录事务把旧目录改名为唯一备份,将新目录改名为正式目标,并在启动前删除备份。两次改名都位于目标卷。这替代了打包记录中基于复制的安装决策。

安装器嵌入固定版本的 7-Zip 命令行工具,为签名发布签署其私有副本,并携带许可证文本。Windows 在复制后的运行时可执行资源签名完成后记录文件清单。解压退出码非零时,旧应用保持完整。上游安装器退出前显式清理目录,也覆盖静默取消。同路径升级跳过旧卸载器,避免其提前删除回滚副本或注册信息。不同路径和安装范围迁移保留 electron-builder 的旧卸载器行为;目录回滚不会撤销这些卸载操作。

影响

目录清理(包括卸载)使用 Windows 扩展长度路径,覆盖深层依赖与备份后缀。新目录替换失败时,安装器尝试恢复已改名的旧目录。如果另一个进程阻止恢复,完整备份仍保留。进程被强制结束或断电可能留下暂存或备份目录;安装器不承诺跨两次改名的崩溃原子性。事务只改变安装文件,不改变外部 Desktop 插件 profile 或产品数据。

考虑过的替代方案

  • 直接覆盖运行中的安装目录。 现有文件占用探针证明,Nsis7z::Extract 可能保留旧文件而不设置 NSIS 错误标志。使用具有退出状态的工具进行暂存,可以避免接受混合版本安装。
  • 解压前删除旧版本。 压缩包损坏或写入失败时,会在替换就绪前移除唯一可用版本。
  • 把 Host 放入 ASAR。 原生模块、包解析和子进程路径需要单独验证;目录替换保留资源布局。

验证

原生目录 smoke在私有目录中调用生产宏。它覆盖首次安装、升级时删除过时文件、目录占用失败、第二次改名失败后的恢复,损坏归档,以及取消清理。模板测试固定暂存早于关闭应用、正式替换早于注册。签名的 0.1.5-rc.2 安装器在 Windows 上通过了首次安装、同路径升级并移除过时文件、文件占用失败后保留旧安装、变更安装位置及完整卸载。每次安装检查都将全部 11,736 个载荷文件与打包目录比对,并验证程序、卸载器签名及注册信息。已安装运行时通过了原生依赖、Web 前端、外部插件路由及实际 Electron 窗口启动和退出检查。最终安装器的一次样本中,首次安装耗时 38.0 秒,同路径升级耗时 27.5 秒,不包含校验和启动,未清空缓存。这些完整安装器观测与上面的组件基线分别记录。线上更新下载和从历史已发布版本升级仍属于发布验收。