Repository navigation
Replies: 5 comments
|
补充一条已实测验证的根因证据,并附上可直接落地的最小修复(rc.1 → rc.2 升级场景实测)。 1. 库侧:安装器被拉起时确实没有 cwd本地 this.spawnLog(installerPath, args).catch((e) => { ... })
2. 应用侧:主进程的 cwd 就是安装目录读取运行中各进程 PEB 的 Windows 不允许重命名「仍被某进程作为当前目录」的目录。因此安装器一旦从安装目录内启动, 3. 对照实验:只换 cwd 就成功同一份 结果:安装成功,注册表 4. 建议修复(
|
|
补充一份同一问题的现场记录(DSH Desktop 0.2.2-rc.1 → 0.2.2-rc.2,Windows 10.0.19045 x64,nightly 通道,安装在 与本帖结论一致的部分:2026-11-12 17:24:57(本地时间),安装器在备份重命名阶段失败,10 次重试全部返回 Windows error 32(另一个程序正在使用此文件), 本贴之外的一个次生现象:安装失败后,17:26:03–17:27:44 连续 8 次启动都在启动阶段崩溃,错误完全一致:
已验证的手动恢复路径(供其他用户参考):
建议:
|
|
补充一份独立现场,并提醒一个与「安装器继承 cwd 自锁」解释存在冲突的源码细节:本机(Windows 11 10.0.26300、按用户安装到 需要确认的点: |
|
@xymdcyy 提到的矛盾是对的,@github-yousen 的修复方向也成立;但持锁者还可以再精确一步——不是安装器自身,而是 0.2.2-rc.2 新增的“安装状态窗口”(release notes 里的 installation-status window)。它解释了为什么 rc.2 这一版是 100% 必现,也解释了为什么只改 spawn cwd 就能绕过。 链路(tag
本机实测(PEB 读 32/64 位进程的
因此修法建议“双保险”:
临时绕过就是 #13025/#13098 已验证的:完全退出 DSH 后,从中性 cwd 运行 历史对照:#11535 也是 error 32 + 10 次重试,但发生在安装状态窗口上线之前(0.2.1-rc.5),持锁来源是残留子进程;#9995/#10851 同一步骤但错误码是 5。因此本条可视为 rc.2 引入的确定性新回归。 |
|
再补一条同机自然实验,用于把「安装器继承 cwd 自锁」与其它持锁者区分开(Windows 10.0.19045,装在
按 @CosMoss114 的链路核对了源码(tag dsh-v0.2.2-rc.2):
因此 @xymdcyy 的观察与持锁者并不矛盾:改名瞬间安装器自身 cwd 确实已是 $PLUGINSDIR,但锁来自更早创建、仍在运行的 rundll32 子进程(它才是继承了安装目录 cwd 的那个)。两条可行修法:给 spawn/ CreateProcess 显式指定 cwd(或保证子进程 cwd 不在安装目录),或不把这类常驻子进程放进 rename 前的路径。这也是我们这次手动安装能绕过去的原因。 |
Uh oh!
There was an error while loading. Please reload this page.
Windows 桌面端自动更新必定失败:更新器拉起安装器时未设置 cwd,安装器继承"安装目录"导致备份改名 MoveFileExW 返回 ERROR_SHARING_VIOLATION(32)
环境
<install-dir>(示例中写作E:\DeepseekHarness,非系统盘、普通 NTFS 目录、剩余空间充足)现象
%LOCALAPPDATA%\@deepseek-aidsh-desktop-updater\pending\deepseek-harness-0.2.2-rc.2-win-x64.exe+update-info.json)。--force-run重新拉起。证据
%LOCALAPPDATA%\@deepseek-aidsh-desktop-updater\installer-logs\directory-failure-20261112-171407.log(4 份日志内容一致,仅 Time/GUID 不同):即:安装器要把旧安装目录整体改名为
.old-{GUID}作为回滚备份,MoveFileExW返回 32(共享冲突/占用),重试 10 次后放弃;Restoration error: 0说明目录本身没被破坏,应用仍能回退到旧版本运行。补充实测:
update-info.json里isAdminRightsRequired: false,排除权限/管理员问题。ProcessParameters.CurrentDirectory:快捷方式「起始位置」= 安装目录时,主进程 cwd 就是E:\DeepseekHarness\。根因
更新链路(Electron + electron-updater + NSIS):
NsisUpdater.doInstall组装["--updated", "/S", "--force-run", "/D=<installDirectory>", "--package-file=<pending exe>"],随后走BaseUpdater.spawnLog(cmd, args):child_process.spawn(cmd, args, { stdio: "ignore", env: undefined, detached: true })—— 未指定cwd,子进程继承父进程的当前目录。process.chdir,所以安装器进程的 cwd 同样是安装目录。MoveFileExW(installDir → installDir.old-{GUID});Windows 不允许重命名任何进程的当前工作目录(哪怕该目录里没有打开的文件句柄),于是必然返回 32,且重试无意义(cwd 不会自己变)。关键点:应用此时已经退出,所以"应用占用安装目录"并不是原因——是安装器自己继承了以安装目录为 cwd 的当前目录,属于自锁。这也解释了为什么"关掉所有 DSH 进程""换时间重试""管理员运行"都无效。
验证
把两个快捷方式(桌面 + 开始菜单)的「起始位置」从安装目录改为中性目录(如
C:\Users\<user>),其余字段(目标、参数、图标)不动,重新从快捷方式启动应用后点更新:C:\Users\<user>;installer-logs不再产生新的directory-failure-*.log。反证:在此之前,每次更新都以同一 error 32 失败。
建议修法
spawnLog显式给安装器一个中性的 cwd,例如app.getPath("temp")。这同时修掉"安装器 cwd 落在安装目录"的一切副作用。System::Call 'kernel32::SetCurrentDirectory(t "$EXEDIR")'(或$TEMP),这样即使宿主没设 cwd 也不会自锁。process.chdir(app.getPath("userData"))),避免快捷方式「起始位置」影响后续子进程。MoveFileExW备份失败时,把installer-logs里的原因回传给主进程并在 UI 上提示(当前静默失败,用户只能看到"版本没变"),同时建议排查 cwd/句柄。临时绕过(用户可用)
任选其一:
DeepSeek Harness.exe会让 cwd 回到安装目录,bug 复发。备注
D:\dee...,0.2.1-rc.5)。本报告补充的是机制层面的根因(更新器 spawn 未设 cwd → 安装器 cwd = 安装目录 → 自锁)以及可复现的绕过方式,可直接用于定位修复。All reactions