fix: use PowerShell 7 and correct shell detection on Windows (Fixes #11958)

This commit is contained in:
3aKHP 2026-03-20 08:57:13 +08:00
parent 137d3f4fd8
commit 28043ff02b
5 changed files with 15 additions and 10 deletions

View file

@ -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<RooTerminal>
@ -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

View file

@ -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<string>("defaultProfile.windows")
const isPowerShell =
process.platform === "win32" &&

View file

@ -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",
}),
)
})

View file

@ -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", () => {

View file

@ -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