Repository navigation
[0.1.7-rc.1][Windows] open-in-app 的「文件资源管理器」静默失效:runNativeCommand 的 windowsHide:true 把 GUI 窗口一起隐藏 #7757
Replies: 2 comments
|
补充一个已验证的最小改法,正好满足你上面提到的「不能全局改」约束。 我在 Windows 11 + dsh 0.1.7-rc.1 上独立复现了完全相同的结论(含单变量 A/B:同一台机、同一条 execFile、只切 // @deepseek-ai/dsh-native-command/lib/index.js — runNativeCommand
// 原:
windowsHide: true
// 改为:
windowsHide: !/(^|[\\/])explorer(\.exe)?$/i.test(command)为什么这样安全:这台机器上经该 runner 派生的外部命令,实际只有 验证方式(不重启 DSH、不经过 UI):从改过的包直接 一处可能同源的遗漏
await run(browser, [path], signal);即经 |
|
补充几条本机核查( 1) 这条链路是两层缺陷叠加,缺任何一层都看不到效果
同一目标、同一 href,只改一个变量:
参数层同样可复现(用 2) 排查陷阱:别用
|
| # | 改动 |
|---|---|
| A | "/select," + explorerTarget(windowsPath) 并进同一个 argv |
| B/C | List() 与 OpenRegistered() 的 handler 读取各加 try/catch,坏 handler 跳过 |
| D1/D2 | runNativeCommand(command, args, signal, overrides = {}) + execFile 选项加 ...overrides(默认仍隐藏) |
| E | run(..., { windowsHide: false }) 只用于 explorer.exe |
验证:补丁后真实调用链跑 reveal → 新窗口 visible=True 且聚焦目标文件;nativeFileApplications 从抛
E_FAIL 变为正常返回已注册 handler 列表。
另外:本仓库已关闭 Issues(
has_issues = false),所以只能发讨论。
5) 顺带:同一条链上还有一个独立缺陷(已另开新帖)
文件卡片走的是 session.workspacePathApplications → nativeFileApplications,与目录级的
/open-in-app/apps 路由不是同一条链。它的 Windows 分支对 IHandler.GetName / GetUIName
零容错:本机存在一个 handler(写字板 WORDPAD 的遗留关联项)这两个方法返回 E_FAIL (0x80004005),
异常冒泡使整个 List() 失败 → 前端 failed = apps === null → 菜单显示「无法获取应用列表」。
ASCII 与中文路径同样受影响。已在另一帖里给出逐 handler 的 HRESULT 探针与修复建议。
Uh oh!
There was an error while loading. Please reload this page.
环境
0.1.7-rc.1(npm i -g @deepseek-ai/dsh@0.1.7-rc.1 --registry=https://registry.npmmirror.com)win32 x64,profile =web@deepseek-ai/dsh-client-ui-open-in-app+@deepseek-ai/dsh-host-open-in-app现象
会话头部的 "Open In…" 分体按钮(当前选中应用为「文件资源管理器」,tooltip 显示
用 文件资源管理器 打开)点击后没有任何反应:打开失败,请重试)POST /open-in-app/openHTTP 200,Size 0.2 kB先排除过:
GET /open-in-app/apps正常(按钮能渲染出来,说明目录解析成功、信任栅栏放行)。所以问题不在“探测”这一环。定位(均为本机实测,非推断)
1. 200 的响应体是
{"ok":true}(11 字节,对上Size 0.2 kB)dsh-host-open-in-app/lib/index.js:⇒ 主机明确判定“已启动”,因此不会走错误分支、不弹提示。
2. 调用链
3.
runExplorer无条件吞掉退出码 1dsh-native-command/lib/index.js:容忍 1 的理由(把请求交接给已在运行的桌面进程后 Explorer 会退 1)是成立的,但实测 Explorer 在「成功打开窗口」时同样返回 1:本机对合法目录执行
explorer.exe <path>,窗口正常打开,$LASTEXITCODE= 1。⇒ 该判据无法区分“已交接”与“什么都没做”。4. 单变量 A/B(同一台机、同一个 node、同一条
execFile,只切windowsHide)execFile('explorer.exe', ['C:\\Users\\<u>\\gh_portable'], { windowsHide: true })execFile('explorer.exe', ['file:///C:/Users/<u>/rust-chan-tdx'], { windowsHide: false })⇒ 差异只有
windowsHide一项。5. 顺带排除了两个方向
file:///URI 形式且成功开窗 ⇒explorerTarget()的 URI 生成是正确的(含非 ASCII 解码回原字符、,→%2C、=→%3D),不是 URI 编码问题explorer走shell-open;windowsterminal(wt -d)、gitbash(git-bash.exe --cd=)等走argv→launchDetachedApp(spawn+detached: true+stdio: 'ignore',windowsHide由条目自己声明),不受影响根因
Node 的
windowsHide: true在 libuv 侧映射为UV_PROCESS_WINDOWS_HIDE(控制台和 GUI 都隐藏),会为子进程设置STARTUPINFO.wShowWindow = SW_HIDE。而
explorer是整个 open-in-app 目录里唯一一个「存在意义就是弹出窗口」的命令 —— 它经runNativeCommand派生,于是窗口被创建成隐藏的。再叠加
runExplorer把退出码 1 一律当作成功,最终表现就是:HTTP 200 + 无窗口 + 无任何提示,使用者完全无从判断。期望
点击后资源管理器窗口可见;且当启动实际未生效时,应能拿到失败信号而不是 200。
可能的修法(供参考)
runNativeCommand增加可选options形参,只有 shell-open 这条路传{ windowsHide: false }。runNativeCommand还被dsh-api-session-controller、dsh-api-settings-controller、dsh-api-workspace-controller、dsh-host-directory-picker-native、图标提取等使用,它们必须保持隐藏,否则会频繁闪控制台窗口。runExplorer不要把退出码 1 无条件当成功(既然它在成功时也出现,就不携带信息)。备注
本条只针对
windowsHide;explorerTarget()的 URI 编码已单独验证为正确,无需改动。上面第 4 点的 A/B 是最小复现,不涉及 dsh 运行时,只需 node。All reactions