From 28043ff02b69053b203cd22d3ab28cfdccd6212c Mon Sep 17 00:00:00 2001 From: 3aKHP <2971755027@qq.com> Date: Fri, 20 Mar 2026 08:57:13 +0800 Subject: [PATCH] fix: use PowerShell 7 and correct shell detection on Windows (Fixes #11958) --- src/integrations/terminal/ExecaTerminalProcess.ts | 3 ++- src/integrations/terminal/TerminalProcess.ts | 4 ++-- .../terminal/__tests__/ExecaTerminalProcess.spec.ts | 10 +++++++--- src/utils/__tests__/shell.spec.ts | 4 ++-- src/utils/shell.ts | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/integrations/terminal/ExecaTerminalProcess.ts b/src/integrations/terminal/ExecaTerminalProcess.ts index cc2af93802..548f3396fc 100644 --- a/src/integrations/terminal/ExecaTerminalProcess.ts +++ b/src/integrations/terminal/ExecaTerminalProcess.ts @@ -5,6 +5,7 @@ import process from "process" import type { RooTerminal } from "./types" import { BaseTerminal } from "./BaseTerminal" import { BaseTerminalProcess } from "./BaseTerminalProcess" +import { getShell } from "../../utils/shell" export class ExecaTerminalProcess extends BaseTerminalProcess { private terminalRef: WeakRef @@ -40,7 +41,7 @@ export class ExecaTerminalProcess extends BaseTerminalProcess { this.isHot = true this.subprocess = execa({ - shell: BaseTerminal.getExecaShellPath() || true, + shell: BaseTerminal.getExecaShellPath() || getShell(), cwd: this.terminal.getCurrentWorkingDirectory(), all: true, // Ignore stdin to ensure non-interactive mode and prevent hanging diff --git a/src/integrations/terminal/TerminalProcess.ts b/src/integrations/terminal/TerminalProcess.ts index d202191b95..117ffc469a 100644 --- a/src/integrations/terminal/TerminalProcess.ts +++ b/src/integrations/terminal/TerminalProcess.ts @@ -97,8 +97,8 @@ export class TerminalProcess extends BaseTerminalProcess { // Execute command const defaultWindowsShellProfile = vscode.workspace - .getConfiguration("terminal.integrated.defaultProfile") - .get("windows") + .getConfiguration("terminal.integrated") + .get("defaultProfile.windows") const isPowerShell = process.platform === "win32" && diff --git a/src/integrations/terminal/__tests__/ExecaTerminalProcess.spec.ts b/src/integrations/terminal/__tests__/ExecaTerminalProcess.spec.ts index 5f0a21869e..7263e5730f 100644 --- a/src/integrations/terminal/__tests__/ExecaTerminalProcess.spec.ts +++ b/src/integrations/terminal/__tests__/ExecaTerminalProcess.spec.ts @@ -21,6 +21,10 @@ vitest.mock("ps-tree", () => ({ default: vitest.fn((_: number, cb: any) => cb(null, [])), })) +vitest.mock("../../../utils/shell", () => ({ + getShell: vitest.fn(() => "/mocked/default/shell"), +})) + import { execa } from "execa" import { ExecaTerminalProcess } from "../ExecaTerminalProcess" import { BaseTerminal } from "../BaseTerminal" @@ -63,7 +67,7 @@ describe("ExecaTerminalProcess", () => { const execaMock = vitest.mocked(execa) expect(execaMock).toHaveBeenCalledWith( expect.objectContaining({ - shell: true, + shell: "/mocked/default/shell", cwd: "/test/cwd", all: true, env: expect.objectContaining({ @@ -105,13 +109,13 @@ describe("ExecaTerminalProcess", () => { ) }) - it("should fall back to shell=true when execaShellPath is undefined", async () => { + it("should fall back to getShell() when execaShellPath is undefined", async () => { BaseTerminal.setExecaShellPath(undefined) await terminalProcess.run("echo test") const execaMock = vitest.mocked(execa) expect(execaMock).toHaveBeenCalledWith( expect.objectContaining({ - shell: true, + shell: "/mocked/default/shell", }), ) }) diff --git a/src/utils/__tests__/shell.spec.ts b/src/utils/__tests__/shell.spec.ts index 8f370e4d7f..5882fdc0a4 100644 --- a/src/utils/__tests__/shell.spec.ts +++ b/src/utils/__tests__/shell.spec.ts @@ -139,11 +139,11 @@ describe("Shell Detection Tests", () => { expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") }) - it("falls back to legacy PowerShell if profile includes 'powershell' but no path/source", () => { + it("falls back to PowerShell 7 if profile includes 'powershell' but no path/source", () => { mockVsCodeConfig("windows", "PowerShell", { PowerShell: {}, }) - expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe") + expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe") }) it("uses WSL bash when profile indicates WSL source", () => { diff --git a/src/utils/shell.ts b/src/utils/shell.ts index 45253c31b0..dc75cf7f4a 100644 --- a/src/utils/shell.ts +++ b/src/utils/shell.ts @@ -205,8 +205,8 @@ function getWindowsShellFromVSCode(): string | null { // If the profile is sourced from PowerShell, assume the newest return SHELL_PATHS.POWERSHELL_7 } - // Otherwise, assume legacy Windows PowerShell - return SHELL_PATHS.POWERSHELL_LEGACY + // Otherwise, assume modern PowerShell 7 (pwsh.exe) as the default + return SHELL_PATHS.POWERSHELL_7 } // If there's a specific path, return that immediately