Repository navigation
[Bug][Windows][桌面端] 「更多打开方式」启动 VS Code 等 Electron 应用失败:ELECTRON_RUN_AS_NODE 泄漏使目标以 Node 模式启动并立即退出 #8483
YOUKNOWWHOOO
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
摘要
官方桌面端(
@deepseek-ai/dsh0.2.0-rc.2)会话头部的「更多打开方式」菜单中,选择 VS Code 会立即弹出「打开失败,请重试」,且系统中不会出现任何 VS Code 进程;同一菜单里的「文件资源管理器(默认)」在同一时刻、对同一目录工作正常。定位结论:桌面端 Host 为把 dsh 服务以 Node.js 模式运行而设置的环境变量
ELECTRON_RUN_AS_NODE=1,被原样传给了它启动的外部应用。VS Code 是 Electron 应用,检测到该变量后以 Node.js 模式启动而非 GUI 模式,随即退出(本机实测退出码1)。Host 把「子进程在看护窗口内以非零退出码结束」判为启动失败,返回 502,前端显示该提示。复现步骤
文件资源管理器(默认)、VS Code、Git Bash。对照:在同一菜单里选择「文件资源管理器(默认)」,该目录可正常打开。
环境
10.0.26200,内部版本26200.8246,64 位,AMD64。0.2.0-rc.2,per-user 安装于%LOCALAPPDATA%\Programs\DeepSeek Harness。44.0.0,内置 Node.js24.18.1,Chromium152.0.7977.54。ELECTRON_RUN_AS_NODE=1拉起的 Node.js 服务,监听127.0.0.1:19387。desktop。1.139.1,per-user 安装于%LOCALAPPDATA%\Programs\Microsoft VS Code;其App Paths\Code.exe注册项与卸载记录均指向实际存在的可执行文件(该可执行文件可被独立启动并正常打开目录)。位置
前端触发点:
dsh-client-ui-open-in-app,目录场景的launch()向POST /open-in-app/open发送{ app, path },非 2xx 即显示path.openError(「打开失败,请重试」)。后端路由:
dsh-host-open-in-app在ctx.webServer上注册的POST /open-in-app/open,命中即调用launchResolved(resolved, path, config.launchWatchMs, …)。启动实现:同包内的
launchDetachedApp,其子进程环境为{ ...scrubbedParentEnv(), ...options.env }。环境清洗规则:
dsh-subprocess的scrubbedParentEnv()只剔除两类名字——匹配/KEY|PASSWORD|SECRET|TOKEN/i的,以及全部DSH_*前缀的。ELECTRON_RUN_AS_NODE不在剔除范围内;VS Code 的启动器也未在options.env里覆盖它。变量来源:
dsh-desktop-host/lib/index.js在为 dsh 服务构造启动环境时显式写入:该变量对 dsh 服务本身是必需的(让它以 Node.js 而非 Electron 模式运行),但它随后的每个子进程都会继承,其中就包括「用某应用打开目录」这条路径启动的外部程序。
观测证据
以下四项在同一台机器上取得。为区分「点击未送达」与「后端失败」,页面上的一切交互均通过 DevTools 协议派发真实鼠标事件(
Input.dispatchMouseEvent),并直接读取页面内fetch的返回。一、后端返回 502,且失败发生在毫秒级
在桌面端页面上下文内直接请求同一端点:
{ "at": "2026-09-30T14:11:28.781Z", "status": 502, "body": "{\"code\":\"launch-failed\",\"message\":\"failed to launch vscode\"}", "elapsedMs": 89 }三次重复的耗时分别为 94 ms、119 ms、89 ms。桌面端 composition 中
launchWatchMs取值为1000(毫秒),因此这不可能是「看护窗口超时」,只能是子进程在看护窗口内提前失败。二、目标进程确实被创建,并在约 86 ms 后退出
在触发请求的同时以 40 ms 间隔轮询系统进程表:
即
Code.exe被成功spawn(不是 ENOENT 类的启动失败),但在极短时间内就结束了。请求在 22:11:28.781 发出、进程于 28.786 创建,两者相差 5 ms。三、对照实验:
ELECTRON_RUN_AS_NODE是唯一分界在同一台机器上以两种环境分别启动同一个
Code.exe,参数均为「打开某个目录」:ELECTRON_RUN_AS_NODEELECTRON_RUN_AS_NODE=11,未出现任何 VS Code 进程 ❌第二种情形与故障现场观测到的「约 86 ms 后退出」一致。
四、变量确实存在于 Host 的子进程环境中
桌面端主进程自身的环境里没有该变量(
mainProcessHasVar: false),说明它不是从用户会话或启动器继承来的;它由dsh-desktop-host在拉取 dsh 服务时写入(见上文「位置」一节的源码片段),而 dsh 服务正是那个承担「打开目录」职责的进程。为什么其它入口不受影响
同一菜单里的三项走的是不同代码路径,这解释了「只有 VS Code 失败」这一现象:
shell-open:交给操作系统 shell 的「打开」动词,不直接 spawn 目标程序argv:spawn(Code.exe, [目录]),继承清洗后的父环境argv:spawnELECTRON_RUN_AS_NODE对其无效果,预期不受影响影响面
ELECTRON_RUN_AS_NODE就会进入 Node.js 模式,因而所有以 Electron 构建的程序都落在这个范围内。按应用目录登记,VS Code、VS Code Insiders、Cursor、Windsurf 属此类;而 Zed、Sublime Text、JetBrains 系 IDE 不是 Electron 程序,不在其列。用户看到的一律是「打开失败,请重试」,且没有指向真实原因的诊断信息。建议
问题出在「dsh 自身需要的 Node 模式标志」与「它启动外部 GUI 应用所需的环境」之间没有隔离。两个可选修复方向:
dsh-host-open-in-app的launchDetachedApp在构造子进程环境时,从scrubbedParentEnv()的结果中删除ELECTRON_RUN_AS_NODE。理由是该变量只对「把 dsh 自身跑成 Node 进程」有意义,而对外部 GUI 应用是有害的;把它一并交给被启动程序,在任何场景下都不是期望行为。dsh-desktop-host改以其它机制让 dsh 服务以 Node 模式运行(例如沿用已经传入的--expose-internals等命令行参数,而不设置ELECTRON_RUN_AS_NODE),从源头避免它对整棵子进程树可见。若短期内不便改动,可考虑在启动失败时把子进程的退出码与信号写入返回体或日志(当前 502 只给出
failed to launch <id>),使同类问题能被直接定位,而不必依赖外部工具观测。All reactions