From 8eb47cb98ef85f8c36730e27fdf3dbf5cbcfbd36 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:33:16 +0000 Subject: [PATCH 1/2] Implement PowerShell fallback support for Windows PowerShell compatibility Co-authored-by: HeyItsGilbert <615265+HeyItsGilbert@users.noreply.github.com> --- src/powershellExecutor.ts | 68 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/src/powershellExecutor.ts b/src/powershellExecutor.ts index 72d82ee..5c206cc 100644 --- a/src/powershellExecutor.ts +++ b/src/powershellExecutor.ts @@ -8,7 +8,7 @@ import { Logger } from './logger'; */ export class PowerShellExecutor { private logger: Logger; - private static readonly POWERSHELL_EXECUTABLE = 'pwsh'; + private powershellExecutable: string | null = null; constructor() { this.logger = Logger.getInstance(); @@ -43,13 +43,71 @@ export class PowerShellExecutor { } } + /** + * Detects which PowerShell executable is available on the system + * Checks for pwsh first (PowerShell 7+), then falls back to powershell (Windows PowerShell 5.1) + */ + private async detectPowerShellExecutable(): Promise { + if (this.powershellExecutable) { + return this.powershellExecutable; + } + + const executablesToTry = ['pwsh', 'powershell']; + + for (const executable of executablesToTry) { + try { + await this.testExecutable(executable); + this.powershellExecutable = executable; + this.logger.info(`Using PowerShell executable: ${executable}`); + return executable; + } catch (error) { + this.logger.debug(`${executable} not available: ${error}`); + } + } + + throw new Error('No PowerShell executable found. Please install PowerShell 7+ (pwsh) or ensure Windows PowerShell (powershell) is available.'); + } + + /** + * Tests if a PowerShell executable is available and working + */ + private testExecutable(executable: string): Promise { + return new Promise((resolve, reject) => { + const ps = childProcess.spawn( + executable, + ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', 'Write-Host "OK"'], + { shell: true } + ); + + let hasOutput = false; + + ps.stdout.on('data', () => { + hasOutput = true; + }); + + ps.on('close', (code: number) => { + if (code === 0 && hasOutput) { + resolve(); + } else { + reject(new Error(`Executable ${executable} exited with code ${code} or produced no output`)); + } + }); + + ps.on('error', (error: Error) => { + // This typically happens when the executable is not found + reject(new Error(`Executable ${executable} not found or failed to start: ${error.message}`)); + }); + }); + } + /** * Checks if PowerShell is available on the system */ public async isPowerShellAvailable(): Promise { try { + const executable = await this.detectPowerShellExecutable(); const output = await this.executeScript('', ['-Command', 'Write-Host "$($PSVersionTable.PSVersion)"']); - this.logger.info(`Detected PowerShell version: ${output.trim()}`); + this.logger.info(`Detected PowerShell version using ${executable}: ${output.trim()}`); return true; } catch (error) { this.logger.warn(`PowerShell not available or failed to execute: ${error}`); @@ -69,9 +127,11 @@ export class PowerShellExecutor { * - Supports both script file execution and direct command execution * - Filters out potentially dangerous arguments for security */ - public executeScript(scriptPath: string, args: string[] = []): Promise { + public async executeScript(scriptPath: string, args: string[] = []): Promise { this.logger.debug(`Executing PowerShell script: ${scriptPath} with args: ${args.join(' ')}`); + const executable = await this.detectPowerShellExecutable(); + // Filter arguments to prevent potentially dangerous operations // Allow only safe PowerShell parameters and user arguments const allowedArgPrefixes = [ @@ -120,7 +180,7 @@ export class PowerShellExecutor { } const ps = childProcess.spawn( - PowerShellExecutor.POWERSHELL_EXECUTABLE, + executable, pwshArguments, { shell: true } ); From 38e495c79d1f509f2bbf47c27e225959220658a6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 Aug 2025 15:21:00 +0000 Subject: [PATCH 2/2] Update CHANGELOG.md with PowerShell fallback support feature Co-authored-by: HeyItsGilbert <615265+HeyItsGilbert@users.noreply.github.com> --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf3871..bc174ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ to structure this file. ## [Unreleased] ### Added +- Windows PowerShell fallback support for better compatibility + - Extension now automatically detects and uses available PowerShell executable + - Tries PowerShell 7+ (`pwsh`) first, then falls back to Windows PowerShell 5.1 (`powershell`) + - Enables extension to work in enterprise environments where only Windows PowerShell is available + - Caches detected executable to avoid repeated detection calls + - Enhanced error handling with clearer error messages when no PowerShell is found - Changelog update instructions to Copilot instructions - Clear process for updating CHANGELOG.md for every PR - Guidelines for using Keep a Changelog format categories