fix(shell): only use string args for cmd.exe on Windows

PowerShell handles array args correctly via CommandLineToArgvW, and
the string form breaks quoted paths ending in backslash (e.g.,
"C:\Temp\") because \" is treated as an escaped quote.

This refines the previous fix to only apply the workaround to cmd.exe.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
tanzhenxin 2026-03-13 15:21:10 +08:00
parent 6193aade55
commit e1dfb4a844
2 changed files with 38 additions and 10 deletions

View file

@ -441,6 +441,29 @@ describe('ShellExecutionService', () => {
});
});
it('should use PowerShell on Windows with array args', async () => {
mockPlatform.mockReturnValue('win32');
mockGetShellConfiguration.mockReturnValue({
executable: 'powershell.exe',
argsPrefix: ['-NoProfile', '-Command'],
shell: 'powershell',
});
await simulateExecution('Test-Path "C:\\Temp\\"', (pty) =>
pty.onExit.mock.calls[0][0]({ exitCode: 0, signal: null }),
);
expect(mockPtySpawn).toHaveBeenCalledWith(
'powershell.exe',
['-NoProfile', '-Command', 'Test-Path "C:\\Temp\\"'],
expect.any(Object),
);
mockGetShellConfiguration.mockReturnValue({
executable: 'bash',
argsPrefix: ['-c'],
shell: 'bash',
});
});
it('should use bash on Linux', async () => {
mockPlatform.mockReturnValue('linux');
await simulateExecution('ls "foo bar"', (pty) =>

View file

@ -418,16 +418,21 @@ export class ShellExecutionService {
try {
const cols = shellExecutionConfig.terminalWidth ?? 80;
const rows = shellExecutionConfig.terminalHeight ?? 30;
const { executable, argsPrefix } = getShellConfiguration();
// On Windows, pass args as a single string instead of an array.
// node-pty's argsToCommandLine re-quotes array elements that contain
// spaces, which mangles user-provided quoted arguments (e.g.,
// `type "hello world"` becomes `"type \"hello world\""`).
// When args is a string, node-pty concatenates it verbatim.
const isWin = os.platform() === 'win32';
const args: string[] | string = isWin
? [...argsPrefix, commandToExecute].join(' ')
: [...argsPrefix, commandToExecute];
const { executable, argsPrefix, shell } = getShellConfiguration();
// On Windows with cmd.exe, pass args as a single string instead of
// an array. node-pty's argsToCommandLine re-quotes array elements
// that contain spaces, which mangles user-provided quoted arguments
// for cmd.exe (e.g., `type "hello world"` becomes
// `"type \"hello world\""`).
//
// For PowerShell, keep the array form: argsToCommandLine escapes for
// CommandLineToArgvW round-tripping, which .NET correctly parses.
// The string form breaks quoted paths ending in \ (e.g., "C:\Temp\")
// because CommandLineToArgvW treats \" as an escaped quote.
const args: string[] | string =
os.platform() === 'win32' && shell === 'cmd'
? [...argsPrefix, commandToExecute].join(' ')
: [...argsPrefix, commandToExecute];
const ptyProcess = ptyInfo.module.spawn(executable, args, {
cwd,