You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
English TL;DR:On this machine the previous DSH install had no HKCU\Software\<GUID>\InstallLocation (private electron-builder key). InstallerPreflight (apps/desktop/installer/path.nsh:120-141) treats a directory as "not ours" whenever that value is absent, even if $INSTDIR\DeepSeek Harness.exe exists. Consequences: (a) silent in-app update (--updated /S --force-run) exits with code 2 at .onInit before touching anything — no dialog, no log, version never changes; (b) the same installer run with the GUI rejects the real installation folder with INSTALLER_PATH_OWNERSHIP. Renaming the old folder (so the target is empty) makes the same installer succeed immediately.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary / 摘要
中文:这台机器上 DSH 桌面端的旧安装从未在注册表写入
HKCU\Software\<GUID>\InstallLocation。而apps/desktop/installer/path.nsh的InstallerPreflight正是用这个值判断“目标目录是不是已注册的安装目录”,取不到就把目录判为“不属于本产品”:electron-updaterspawnpending\...exe --updated /S --force-run,静默)→ preflight 失败 →SetErrorLevel 2+Quit,UI 无任何错误、没有日志、没有任何文件被写,界面停在 ready,用户只能反复点“安装并重启”;INSTALLER_PATH_OWNERSHIP(“请选择空文件夹,或 DeepSeek Harness 原来的安装目录”),退出码2,安装目录原封不动。把旧目录改名使目标路径变空后,同一个安装包一次装成功(exit 0),并把私有键和卸载项的
InstallLocation都写入了。English TL;DR:On this machine the previous DSH install had no
HKCU\Software\<GUID>\InstallLocation(private electron-builder key).InstallerPreflight(apps/desktop/installer/path.nsh:120-141) treats a directory as "not ours" whenever that value is absent, even if$INSTDIR\DeepSeek Harness.exeexists. Consequences: (a) silent in-app update (--updated /S --force-run) exits with code2at.onInitbefore touching anything — no dialog, no log, version never changes; (b) the same installer run with the GUI rejects the real installation folder withINSTALLER_PATH_OWNERSHIP. Renaming the old folder (so the target is empty) makes the same installer succeed immediately.Reproduction / 复现步骤
HKCU\Software\<GUID>\InstallLocation”的机器上启动 0.2.2-rc.1(per-user 安装,C:\Users\<user>\AppData\Local\Programs\DeepSeek Harness)。0.2.2-rc.2并下载完成(状态变 ready)。%TEMP%下出现 NSIS 插件目录),但安装目录没有任何文件被替换;重开后仍是 rc.1。%LOCALAPPDATA%\@deepseek-aidsh-desktop-updater\pending\deepseek-harness-0.2.2-rc.2-win-x64.exe(GUI):目录页已经识别出原安装目录,点“安装”立即弹INSTALLER_PATH_OWNERSHIP,退出码 2。关于“注册表项缺失”的来源:本机不是通过解压
app-64.7z安装的(目录内有安装器写入的Uninstall DeepSeek Harness.exe,时间戳与安装目录一致),但实测两个键都不存在(见 §Evidence)。这条 issue 描述的是这一类状态造成的结果——无论该状态是安装器异常退出、注册表被清理,还是上游 §Root cause 提到的键不对称造成,症状与修复路径相同。Current behavior / 实际结果
DesktopUpdateCoordinator.install()已经把状态置为installing,beforeRestart()也全部通过(应用确实退出、安装器确实被 spawn),失败发生在安装器进程内部,外壳拿不到任何信号,UI 回到 ready,用户除了“再点一次”没有别的可做。%TEMP%\ns*.tmp里残留的$PLUGINSDIR\window-frame.dll;@deepseek-aidsh-desktop-updater\installer-logs\下没有任何 preflight 报告(该目录只在 extract/directory 阶段失败时才写)。INSTALLER_PATH_OWNERSHIP拒绝真实安装目录,退出码 2。Expected behavior / 期望结果
%LOCALAPPDATA%\@deepseek-aidsh-desktop-updater\installer-logs\preflight-failure-*.log(含InstallLocation的期望值/实际值、$INSTDIR、exit code),并把安装器的退出码回传为 UI 上的可见失败(现在install阶段只有error分支才提示,而这条路径不产生 error)。InstallLocation缺失但$INSTDIR等于默认安装目录、且$INSTDIR\DeepSeek Harness.exe与$INSTDIR\resources\app-update.yml都存在时,视为既有安装(至少提示“修复注册表并继续”),不要要求用户改名目录才能升级。customInstall显式写的是${UNINSTALL_REGISTRY_KEY}的InstallLocation(scripts/installer.nsh:253),而 preflight 读的是${INSTALL_REGISTRY_KEY}(path.nsh:127);建议两处都写,避免私有键缺失时永远无法自愈。DesktopUpdateJournal目前仅在DSH_DESKTOP_UPDATE_JOURNAL_DIR存在时创建,导致这类事故“零证据”。Environment / 环境
0.2.2-rc.1(app.asar!package.json= 0.2.2-rc.1,exe FileVersion = 0.2.2-rc.1)0.2.2-rc.2(安装后 exe FileVersion = 0.2.2-rc.2,dshBuildCommit=a6b1b85f44891ee1484bed6a9fc08acaae777d90)nightly,https://download.deepseek.com/dsh-desk/feeds/win-x64/C:\Users\<user>\AppData\Local\Programs\DeepSeek Harness(路径无空格以外特殊字符,本地固定磁盘 NTFS)deepseek-harness-0.2.2-rc.2-win-x64.exe,299,659,528 B;AuthenticodeValid(CN="Hangzhou DeepSeek Artificial Intelligence Co., Ltd.");SHA-512(base64) 与pending\update-info.json完全一致:5rRAkVruKkm4KELAbTqV8ZFrMwSo3oESnzXb9ebkJWPCMe6WuHORQZR63uY+BqAc6sBdyBtwSelsCGh0k1NcJA==Evidence / 证据
时间线(UTC+8,2026-11-12):
@deepseek-aidsh-desktop-updater\current.blockmap写入pending\deepseek-harness-0.2.2-rc.2-win-x64.exe(299,659,528 B)落盘pending\update-info.json(sha512 如上,校验通过)%TEMP%\nsaEFFB.tmp出现,内含且仅含$PLUGINSDIR\window-frame.dll(169,968 B)→ 应用内更新 spawn 的安装器%TEMP%\nso47ED.tmp,同上 → 第二次点“安装并重启”11-04 17:30:40,DeepSeek Harness.exeFileVersion 仍为0.2.2-rc.1/S):8 秒后退出码2,目录未变DeepSeek Harness.rc1-backup-*),目标路径为空0DeepSeek Harness.exeFileVersion =0.2.2-rc.2,app.asar内package.json= 0.2.2-rc.2 ✅注册表(安装前,
HKCU,全部为只读扫描):HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall下没有DeepSeek Harness项;HKCU\Software两级,只有OpenCode、MinerU的 GUID 键带InstallLocation,没有任何键指向 DSH 安装目录。注册表(12:54 安装成功后新增):
Root cause / 源码定位
apps/desktop/installer/path.nsh(L120–141):关键点:
InstallLocation为空时$0 != $INSTDIR恒成立,于是直接进入“非空目录 → 拒绝”的分支——$INSTDIR\DeepSeek Harness.exe存在并不能救场(那个FileExists是OrIfNot,只会让条件更容易成立)。唯一的凭据就是注册表相等。静默路径把它变成“零反馈”(
apps/desktop/scripts/installer.nshL75–82):Quit发生在InitPluginsDir之后,所以%TEMP%\ns*.tmp会留下window-frame.dll,而 preflight 阶段还没有任何 report 写入 → 用户侧零线索。这也解释了为什么“应用正常退出 + 安装器确实被拉起”的机器仍然永远升级不了。次要观察(不确定性已在文中标注):
scripts/installer.nshL253 的customInstall只写了${UNINSTALL_REGISTRY_KEY}的InstallLocation,preflight 读的是${INSTALL_REGISTRY_KEY};私有键若因任何原因缺失,安装器无法通过“再装一次”自愈,只能把目录清空重装。Workaround / 规避(本机已验证)
DeepSeek Harness.exe)。DeepSeek Harness.old),使目标路径不存在或为空。%LOCALAPPDATA%\@deepseek-aidsh-desktop-updater\pending\deepseek-harness-<version>-win-x64.exe,目录填回原路径,正常 GUI 安装。HKCU\Software\<GUID>\InstallLocation与卸载项都已写入 → 之后应用内更新可以过 preflight。(同一思路也可用
/S /D=<安装目录>静默完成,/D必须放最后且不加引号。)Related / 相关讨论
%TEMP%\ns*.tmp里只剩window-frame.dll——足迹相同,但失败点不同(那条是InstallerCheckAppRunning)。INSTALLER_PATH_INVALID全拒(AppData 被重定向的机器),最终也是“解出app-64.7z直接用”,代价同样是丢注册项。beforeRestart()/update-tasks/ teardown 相关的失败;本例不涉及——日志与进程时间线显示应用正常退出、安装器确实被 spawn。All reactions