Skip to content

fix(windows): hide the console window forked by the console-list agent - #966

Open
Aikio (Aikiooo) wants to merge 1 commit into
microsoft:mainfrom
Aikiooo:fix/hide-console-list-agent-window
Open

Aikio (Aikiooo) wants to merge 1 commit into
microsoft:mainfrom
Aikiooo:fix/hide-console-list-agent-window

Conversation

@Aikiooo

Copy link
Copy Markdown

What

WindowsPtyAgent.kill() calls _getConsoleProcessList(), which forks conpty_console_list_agent:

const agent = fork(path.join(__dirname, 'conpty_console_list_agent'), [ this._innerPid.toString() ]);

fork() inherits stdio, so on Windows that child is given a console of its own. The result is a console window appearing on screen every time a pty is killed. In an embedding application it can also take focus away from the host's window, which is how it surfaced for us.

Change

Pass windowsHide: true to that fork. The helper still gets a console — it needs one, because getConsoleProcessList() calls FreeConsole() and then AttachConsole(shellPid) — it just has no window.

fork() spreads its options through to spawn() (options = { __proto__: null, ...options, shell: false }), which honours windowsHide, so nothing else about how the helper is started changes.

Why the local is typed

windowsHide is honoured at runtime but is missing from @types/node's ForkOptions — still true on DefinitelyTyped master — so passing it inline does not compile against strict:

error TS2353: Object literal may only specify known properties, and 'windowsHide' does not exist in type 'ForkOptions'.

The options object is typed with a cast to keep the build green. Happy to send the DefinitelyTyped change instead and drop the cast if you'd prefer that first.

Verification

  • npm run build (tsc, strict) and npm run lint pass.
  • Full mocha suite: 57 passing, 0 failing, which includes kill › should kill the process tree on the path this touches (useConptyDll = false). It polls the real process tree and still sees it removed, so the console-list sweep is unaffected by hiding the console.
  • The agent itself, queried directly against a live pty with and without the option, attaches either way and returns the shell pid in the list (45 ms vs 37 ms, no timeout).

Not covered here

WindowsPtyAgent.kill() calls _getConsoleProcessList(), which forks
conpty_console_list_agent. fork() inherits stdio, so on Windows that child is
given a console of its own, and a console window appears every time a pty is
killed. In an embedding application it can also take focus from the host's
window.

windowsHide still leaves the helper a console - it needs one, because
getConsoleProcessList() calls FreeConsole() then AttachConsole(shellPid) - it
just gives it no window.

@types/node's ForkOptions does not declare windowsHide (still true on
DefinitelyTyped master), so the options object is typed to keep strict
building.
@Aikiooo
Aikio (Aikiooo) force-pushed the fix/hide-console-list-agent-window branch from 05644ea to a9483f0 Compare September 10, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant