docs(native-command): correct the non-interactive Explorer claim

The recorded exit code 0 after about 30 seconds was not reproduced: an SSH
session 0 on Windows 11 ARM64 build 26200 measured exit code 1 after about a
second with no association invoked, the same exit code a delegated open
returns. The README, both Agent Note languages, and the `explorerTarget` JSDoc
now record that measurement, and the `Invoke-Item` contrast keeps its
qualitative part without the timing.
This commit is contained in:
mektpoy committed 2026-09-22 20:29:24 +08:00
1 parent b73031be9b
commit a6b909c767
7 files changed
+12 -9

No files matched your search

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-09-22-windows-open-through-shell-resolution.md
2026-09-22-windows-open-through-shell-resolution.md: dac6b089d8d69d40a4cd7c92f4f74ee06f304329
2026-09-22-windows-open-through-shell-resolution.zh.md: 8d2a00c6769906b568f605451d2afe339aed6dcf
2026-09-22-windows-open-through-shell-resolution.md: 50caa066613ec372cbaef720e0bae575f800a162
2026-09-22-windows-open-through-shell-resolution.zh.md: a7c7e4eeeb08e2c6e74fb0e24268ca4ea650d335
@@ -34,7 +34,7 @@ The settings sheet's open gesture and the artifact and workspace opens share one
The opener can no longer distinguish "the shell opened it" from "the shell declined": Explorer reports 0 or 1 for both, so the Remote still answers `{ opened: true }`, and a machine with no handler shows the shell's chooser as its only feedback. Nothing here verifies that a window appeared.
An interactive desktop session is a precondition. In a non-interactive Windows session (a service, or a scheduled task without an interactive logon) `explorer.exe` returned exit code 0 after about 30 seconds without invoking any association, where an `Invoke-Item` command opened the file in about 0.35 seconds: a Host started that way loses the capability and pays the wait, and a caller's abort signal is what bounds it. No fallback for that session is implemented.
An interactive desktop session is a precondition. In a non-interactive Windows session (a service, or a scheduled task without an interactive logon) `explorer.exe` invokes no association and still exits 1, so that exit code does not tell this case apart from a delegated open: an SSH session 0 on Windows 11 ARM64 build 26200 measured exit code 1 after about a second, where an `Invoke-Item` command resolved the association in-process. A Host started that way loses the capability and pays the wait, and a caller's abort signal is what bounds it. No fallback for that session is implemented.
Directories take the same path. The rejected alternative recorded in [the open-in-app note](../feature/2026-08-25-promote-open-anywhere-plugin.md) was a detached, credential-scrubbed `explorer.exe <dir>` spawn, which is not what this handoff does: the `explorer.exe` child inherits the host environment and no detached process is created, while the application or folder window Explorer delegates to starts from the desktop session's environment rather than the host's.
@@ -34,7 +34,7 @@ Windows 对 HTML 与 SVG 仍然无法命名浏览器,因此 `openInBrowser`
打开器再也无法区分「shell 打开了」与「shell 拒绝了」:两种情况 Explorer 都返回 0 或 1,因此 Remote 依旧回答 `{ opened: true }`,完全没有处理程序的机器只能看到 shell 的选择框。此处不校验窗口是否真的出现。
交互桌面会话现在是前提。在非交互 Windows 会话(服务,或没有交互登录的计划任务)中,`explorer.exe` 在约 30 秒后以退出码 0 返回且不调用任何关联,而 `Invoke-Item` 命令在同一会话里约 0.35 秒就打开了文件:这样启动的 Host 既失去能力又要付等待代价,只有调用方的 abort 信号能给这段等待封顶。该会话下的兜底尚未实现。
交互桌面会话现在是前提。在非交互 Windows 会话(服务,或没有交互登录的计划任务)中,`explorer.exe` 不调用任何关联,且同样以退出码 1 返回,因此该退出码无法与「已委派」区分:Windows 11 ARM64 build 26200 的 SSH session 0 实测约 1 秒后返回退出码 1,而同一会话里 `Invoke-Item` 命令能在进程内解析关联。这样启动的 Host 会失去能力且要付出等待,只有调用方的 abort 信号能给这段等待封顶。该会话下的兜底尚未实现。
目录走同一条路径。[open-in-app 记录](../feature/2026-08-25-promote-open-anywhere-plugin.zh.md)中被否决的方案是 detached 且经过凭据清洗的 `explorer.exe <dir>` 派生进程,那不是本交接的做法:`explorer.exe` 子进程继承宿主环境,也不创建 detached 进程;而它转交给桌面会话启动的应用或文件夹窗口,继承的是桌面会话环境而不是宿主进程环境。
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/util/native-command/README.md
README.md: 72c9d0097975773d316e3f2fdba87da1eca4daa4
README.zh.md: 35770a99756a9eb218b024406690b340c09bfd84
README.md: 537101a2e1a5e60c1ea1c25d0700ae26d3f4df43
README.zh.md: f7783a503a84baf0e78572b07794e17d6100e082
+1 -1
View File
@@ -109,7 +109,7 @@ Linux association discovery and explicit launching require GIO. Missing native c
These limits define when this runner is not the right tool. They are current package constraints, not a task backlog.
- Command output uses Node’s `execFile` buffer limit; oversized replies reject. Use the subprocess capability for streaming output.
- A Windows host needs an interactive desktop session. In a non-interactive session — a service, or a scheduled task without an interactive logon — `explorer.exe` returns exit code 0 after about 30 seconds without invoking any file association, so an open reports success having opened nothing; a caller's abort signal turns that wait into a timeout rather than a hang. An `Invoke-Item` command resolves the association in-process there in about 0.35 seconds, and its directory failure arrives as a non-zero exit code. No fallback for that session is implemented.
- A Windows host needs an interactive desktop session. In a non-interactive session — a service, or a scheduled task without an interactive logon — `explorer.exe` invokes no file association and still exits 1 after about a second (an SSH session 0 on Windows 11 ARM64 build 26200), so an open reports success having opened nothing; a caller's abort signal turns that wait into a timeout rather than a hang. An `Invoke-Item` command resolves the association in-process there, and its directory failure arrives as a non-zero exit code. No fallback for that session is implemented.
<a id="dev-note"></a>
### Dev Note
+1 -1
View File
@@ -109,7 +109,7 @@ Linux 的关联查询和指定应用启动需要 GIO。缺少原生命令时查
这些限制说明本运行器何时不是合适的工具。它们是当前包约束,不是任务积压。
- 命令输出受 Node 的 `execFile` 缓冲上限约束,超过上限时拒绝结果。流式输出由 subprocess 能力处理。
- Windows 主机需要交互桌面会话。在非交互会话(服务,或没有交互登录的计划任务)中,`explorer.exe` 会在约 30 秒后以退出码 0 返回且不调用任何文件关联,于是「打开」会报告成功却什么都没打开;调用方的 abort 信号把这段等待变成超时而不是挂死。同一目标改用 `Invoke-Item` 命令时,该会话内约 0.35 秒即可在进程内解析关联,目录失败也会以非零退出码报出。该会话下的兜底尚未实现。
- Windows 主机需要交互桌面会话。在非交互会话(服务,或没有交互登录的计划任务)中,`explorer.exe` 不调用任何文件关联,且仍在约 1 秒后以退出码 1 返回(Windows 11 ARM64 build 26200 的 SSH session 0 实测),于是「打开」会报告成功却什么都没打开;调用方的 abort 信号把这段等待变成超时而不是挂死。同一目标改用 `Invoke-Item` 命令时可在该会话内解析关联,目录失败也会以非零退出码报出。该会话下的兜底尚未实现。
<a id="dev-note"></a>
### 开发备注
@@ -104,7 +104,10 @@ function isWsl(internals: PathOpenerInternals): boolean {
* so a path handed over raw loses everything after its first comma and the
* shell opens a different target without reporting it. A file URI has `,`
* percent-encoded and keeps whitespace, and Explorer resolves it to the shell
* item the path names.
* item the path names. Node resolves the path before encoding it, so a verbatim
* `\\?\` or `\\?\UNC\` prefix reaches Explorer as the ordinary drive or UNC
* URI; a `\\.\` device path keeps that same UNC handling and names a device
* rather than a shell item, which this opener does not open.
* @param windowsPath - path already translated for the Windows desktop.
* @returns the target for an open, or the object of a `/select,` reveal.
*/