[Bug] Windows 桌面版自动更新必现失败:会话运行时退出收尾挂起(「无法关闭 ZCode」);静默更新以退出码 2 失败且原因被静默吞掉
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
问题类别 · Category
稳定性 / 崩溃 · Stability / Crash(更新器 / 安装器 · Updater / Installer)
问题描述 · Description
Windows 桌面版的自动更新在两个环节各有一个缺陷,叠加导致应用内自动更新在本机 100% 失败,用户被迫手动重装。两个缺陷均已定位到代码级根因,供参考:
缺陷 A:有会话运行时,退出收尾挂起 → 安装器报"无法关闭 ZCode"
点击「立即重启更新」后,应用启动 NSIS 安装器并开始退出。主进程的 before-quit 是两阶段退出:先 e.preventDefault(),执行异步的会话优雅收尾(y$("app-before-quit")),完成后再真正 app.quit()。当存在运行中的 agent 会话时,该收尾可能长时间不结束,ZCode.exe 进程不退出,NSIS 安装器的关闭检查(CHECK_APP_RUNNING)等待超时后弹出「无法关闭 ZCode」并中止更新。
缺陷 B:静默更新(/S)以退出码 2 失败,失败原因被静默吞掉
即使应用已完全关闭,静默安装仍然 100% 失败。根因在 electron-builder 的更新流程:安装新版本前必须先运行旧版本的卸载器(installUtil.nsh 的 uninstallOldVersion)。本机旧卸载器必然失败(触发条件见下),于是:
UninstallLoop以 1 秒间隔重试 5 次(与实测的 44 秒安装时长完全吻合);- 重试耗尽后
MessageBox MB_RETRYCANCEL ... /SD IDCANCEL——静默模式下报错弹窗被自动确认为"取消",用户完全看不到任何失败信息; handleUninstallResult执行SetErrorLevel 2后退出。
旧卸载器失败的触发条件:应用「设置/关于」或卸载注册表项 HKCU\...\Uninstall\{guid} 的 InstallLocation 值为空(手动重装历史容易造成),此时旧卸载器的卸载目标解析失败。
复现步骤 · Steps to reproduce
缺陷 A:
- 正常使用 ZCode,保持至少一个 agent 会话处于运行状态
- 点击「检查更新」→ 下载完成 → 点击「立即重启更新」
- 弹出「无法关闭 ZCode」,更新中止
缺陷 B:
- 退出 ZCode,确认
ZCode.exe进程数为 0 - 以静默模式运行安装包:
ZCode-3.10.2-win-x64.exe /S --force-run(与 electron-updater 传参一致) - 约 44 秒后进程退出,退出码恒为 2,安装目录无任何变化
期望表现 · Expected behavior
- 更新时无论是否有运行中的会话,应用都应能在有限时间内完成退出(如收尾加超时兜底、超时后强制结束工作进程)
- 静默更新失败时不应无提示退出:应把失败原因写入日志文件,且安装器退出码应能区分「关闭应用失败」「卸载旧版本失败」「复制文件失败」等不同阶段
- 卸载注册表项缺少
InstallLocation时应能自我修复(从安装器自身路径推断),而不是让更新流程永久卡死
实际表现 · Actual behavior
- 缺陷 A:弹「无法关闭 ZCode」,更新中止;
%TEMP%残留未清理的nsu*.tmp(内含 UAC.dll、System.dll) - 缺陷 B:44 秒后静默退出(exit code 2),无日志、无弹窗、安装目录无变化。主进程日志(
~/.zcode/v2/logs/)中更新器全程零输出,用户无法自行排查
关键证据
- 退出码 2 的来源(electron-builder
installUtil.nsh):
以及${if} $R0 != 0 MessageBox MB_OK|MB_ICONEXCLAMATION "$(uninstallFailed): $R0" /SD IDOK DetailPrint `Uninstall was not successful. Uninstaller error code: $R0.` SetErrorLevel 2 Quit ${endif}UninstallLoop的 5 次重试逻辑(1 秒间隔 × 5 次 + 解压时间 ≈ 44 秒,与实测吻合) - 本机注册表卸载项在修复前:
DisplayName="ZCode 3.10.1",InstallLocation(空)、InstallDate(空) - 修复方式(本机已用此法成功升级 3.10.2):用 7-Zip 解开安装包(848 个文件)直接覆盖安装目录,并补齐注册表
InstallLocation/DisplayVersion——这也反向印证了缺陷 B 的根因在"卸载旧版本"环节而非文件写入环节
环境信息
- ZCode 版本 · Version: 受影响 3.10.1.6272(及更早);当前已手动升级到 3.10.2.6414
- 设备 / 系统 · OS: Windows 10 Pro 22621 x64(内置 Administrator 账户,非 UAC 受限);安装目录
D:\软件\Zcode - 复现频率 · Frequency: 必现 · Always(缺陷 A:会话运行时必现;缺陷 B:本机静默模式必现)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the Electron before-quit flow around y$("app-before-quit") and the updater’s NSIS path, then compare it with electron-builder’s installUtil.nsh, UninstallLoop, and handleUninstallResult. Reproduce both session-running and /S failures using the supplied steps. Done means bounded shutdown, logged silent failures with distinct exit codes, and recovery when the uninstall registry entry lacks InstallLocation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron
- Domain
- desktop, release
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100