diff --git a/packages/core/src/ide/process-utils.test.ts b/packages/core/src/ide/process-utils.test.ts index db9f4982868..1eae3605258 100644 --- a/packages/core/src/ide/process-utils.test.ts +++ b/packages/core/src/ide/process-utils.test.ts @@ -71,9 +71,15 @@ describe('getIdeProcessInfo', () => { command: 'C:\\Program Files\\VSCode\\Code.exe', }); expect(mockedExec).toHaveBeenCalledWith( - expect.stringContaining( - 'Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,Name,CommandLine', - ), + 'powershell.exe', + expect.arrayContaining([ + '-NoProfile', + '-NonInteractive', + '-Command', + expect.stringContaining( + 'Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,Name,CommandLine', + ), + ]), expect.anything(), ); }); @@ -142,11 +148,39 @@ describe('getIdeProcessInfo', () => { const result = await getIdeProcessInfo(); expect(result).toEqual({ pid: 900, command: 'powershell.exe' }); expect(mockedExec).toHaveBeenCalledWith( - expect.stringContaining('Get-CimInstance Win32_Process'), + 'powershell.exe', + expect.arrayContaining([ + '-NoProfile', + '-NonInteractive', + '-Command', + expect.stringContaining('Get-CimInstance Win32_Process'), + ]), expect.anything(), ); }); + it('should invoke powershell.exe with -NoProfile -NonInteractive flags', async () => { + (os.platform as Mock).mockReturnValue('win32'); + const processes = [ + { + ProcessId: 1000, + ParentProcessId: 0, + Name: 'node.exe', + CommandLine: 'node.exe', + }, + ]; + mockedExec.mockResolvedValueOnce({ stdout: JSON.stringify(processes) }); + + await getIdeProcessInfo(); + + expect(mockedExec).toHaveBeenCalledTimes(1); + const [program, args] = mockedExec.mock.calls[0]; + expect(program).toBe('powershell.exe'); + expect(args).toContain('-NoProfile'); + expect(args).toContain('-NonInteractive'); + expect(args).toContain('-Command'); + }); + it('should handle short process chains', async () => { (os.platform as Mock).mockReturnValue('win32'); // process (1000) -> root (0) diff --git a/packages/core/src/ide/process-utils.ts b/packages/core/src/ide/process-utils.ts index 6708d53ed7e..06367b15b6d 100644 --- a/packages/core/src/ide/process-utils.ts +++ b/packages/core/src/ide/process-utils.ts @@ -4,12 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { exec } from 'node:child_process'; +import { exec, execFile } from 'node:child_process'; import { promisify } from 'node:util'; import os from 'node:os'; import path from 'node:path'; const execAsync = promisify(exec); +const execFileAsync = promisify(execFile); const MAX_TRAVERSAL_DEPTH = 32; @@ -37,9 +38,13 @@ async function getProcessTableWindows(): Promise> { const powershellCommand = 'Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,Name,CommandLine | ConvertTo-Json -Compress'; // Increase maxBuffer to handle large process lists (default is 1MB) - const { stdout } = await execAsync(`powershell "${powershellCommand}"`, { - maxBuffer: 10 * 1024 * 1024, - }); + const { stdout } = await execFileAsync( + 'powershell.exe', + ['-NoProfile', '-NonInteractive', '-Command', powershellCommand], + { + maxBuffer: 10 * 1024 * 1024, + }, + ); if (!stdout.trim()) { return processMap;