From 2fd7f7ca52750f616d47a20522f3264354a6234b Mon Sep 17 00:00:00 2001 From: lawrence3699 Date: Thu, 2 Apr 2026 16:32:47 +1100 Subject: [PATCH] fix(exec): hide windows console windows --- src/process/exec.ts | 5 +++-- src/process/exec.windows.test.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/process/exec.ts b/src/process/exec.ts index fcb7b35a90f..166dbf32fb2 100644 --- a/src/process/exec.ts +++ b/src/process/exec.ts @@ -133,9 +133,9 @@ export async function runExec( ? await execFileAsync( process.env.ComSpec ?? "cmd.exe", ["/d", "/s", "/c", buildCmdExeCommandLine(execCommand, execArgs)], - { ...options, windowsVerbatimArguments: true }, + { ...options, windowsVerbatimArguments: true, windowsHide: true }, ) - : await execFileAsync(execCommand, execArgs, options); + : await execFileAsync(execCommand, execArgs, { ...options, windowsHide: true }); if (shouldLogVerbose()) { if (stdout.trim()) { logDebug(stdout.trim()); @@ -261,6 +261,7 @@ export async function runCommandWithTimeout( stdio, cwd, env: resolvedEnv, + windowsHide: true, windowsVerbatimArguments: useCmdWrapper ? true : windowsVerbatimArguments, ...(shouldSpawnWithShell({ resolvedCommand, platform: process.platform }) ? { shell: true } diff --git a/src/process/exec.windows.test.ts b/src/process/exec.windows.test.ts index d57ce924543..048d962c935 100644 --- a/src/process/exec.windows.test.ts +++ b/src/process/exec.windows.test.ts @@ -79,6 +79,7 @@ function expectCmdWrappedInvocation(params: { expect(params.captured[0]).toBe(params.expectedComSpec); expect(params.captured[1].slice(0, 3)).toEqual(["/d", "/s", "/c"]); expect(params.captured[1][3]).toContain("pnpm.cmd --version"); + expect(params.captured[2].windowsHide).toBe(true); expect(params.captured[2].windowsVerbatimArguments).toBe(true); } @@ -145,6 +146,7 @@ describe("windows command wrapper behavior", () => { path.join(path.dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"), ); expect(captured[1][1]).toBe("--version"); + expect(captured[2].windowsHide).toBe(true); expect(captured[2].windowsVerbatimArguments).toBeUndefined(); expect(captured[2].stdio).toEqual(["inherit", "pipe", "pipe"]); } finally { @@ -172,6 +174,7 @@ describe("windows command wrapper behavior", () => { expect(captured[0]).toBe(expectedComSpec); expect(captured[1].slice(0, 3)).toEqual(["/d", "/s", "/c"]); expect(captured[1][3]).toContain("npm.cmd --version"); + expect(captured[2].windowsHide).toBe(true); expect(captured[2].windowsVerbatimArguments).toBe(true); expect(captured[2].stdio).toEqual(["inherit", "pipe", "pipe"]); } finally { @@ -261,4 +264,32 @@ describe("windows command wrapper behavior", () => { platformSpy.mockRestore(); } }); + + it("sets windowsHide on direct runExec invocations too", async () => { + const platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + + execFileMock.mockImplementation( + ( + _command: string, + _args: string[], + _options: Record, + cb: (err: Error | null, stdout: string, stderr: string) => void, + ) => { + cb(null, "ok", ""); + }, + ); + + try { + await runExec("node", ["--version"], 1000); + const captured = execFileMock.mock.calls[0] as ExecCall | undefined; + if (!captured) { + throw new Error("expected direct execFile invocation"); + } + expect(captured[0]).toBe("node"); + expect(captured[1]).toEqual(["--version"]); + expect(captured[2].windowsHide).toBe(true); + } finally { + platformSpy.mockRestore(); + } + }); });