Optimize PowerShell availability check: file existence fast path with automatic recovery#2596
Optimize PowerShell availability check: file existence fast path with automatic recovery#2596
Conversation
…processes Co-authored-by: nagilson <23152278+nagilson@users.noreply.github.com>
| { | ||
| // Fast path: check if the PowerShell executable exists at the well-known absolute path before | ||
| // spawning processes to validate, as process-based validation can take several seconds on some systems. | ||
| const systemRoot = process.env.SystemRoot ?? process.env.SYSTEMROOT ?? 'C:\\Windows'; |
There was a problem hiding this comment.
@copilot This approach seems reasonable, but we should be able to recover from the fast mode logic if it fails and then try the full logic as implemented in the function again, and then try to run the command using the other powershell reference.
Note by fails, I don't mean if the install script itself fails, but if we instead get a specific failure like ENOENT (or the process could not be found, etc) - please test this manually to see what errors are possible (e.g. bad file there (non executable, not powershell executable, etc, or if there's a better way to test if this works)
There was a problem hiding this comment.
Updated in 745b56a. The fast path now:
- Checks if
powershell.exeexists at the well-known path - If found, runs a quick single-process execution test (
execute('0', [], { shell: defaultPowershellPath })) - If the test succeeds (exit status
'0'), returns the path immediately - If the test throws any error (ENOENT, bad/non-PowerShell executable, etc.), catches it and falls through to the full
tryFindWorkingCommand()validation that tries all alternative paths (powershell.exe,%SystemRoot%\...\powershell.exe,pwsh,powershell)
There was a problem hiding this comment.
@copilot Hold on, the point of this PR is that we don't spawn a whole process to do this and assume that the path works by default. Instead, we should be able to recover later when we try to run the script with powershell and it doesn't exist, and can run this check and then call the existing implementation (but with the context of the path that already does not work)
There was a problem hiding this comment.
Updated in f0c2fc1. verifyPowershellCanRun() now does a file-existence-only check (no process spawning) — if the file is at the well-known path, it's returned immediately. Recovery from a broken fast-path path happens later in installDotnet(): the cp.exec call is now wrapped in a runInstall(cmd, psRef, isRetry) inner helper. When the first attempt fails with cmd.exe-level "process not found" patterns in stderr (e.g. "is not recognized as an internal or external command"), it calls findWorkingPowershellViaProbing() (the extracted slow tryFindWorkingCommand path) and retries once with the discovered alternative.
… test fails Co-authored-by: nagilson <23152278+nagilson@users.noreply.github.com>
…lDotnet when PS process launch fails Co-authored-by: nagilson <23152278+nagilson@users.noreply.github.com>
PowerShell validation was taking ~7 seconds on some Windows systems because
verifyPowershellCanRun()unconditionally spawned PowerShell processes to probe each candidate path viatryFindWorkingCommand().Changes
verifyPowershellCanRun(): Check ifpowershell.exeexists at the well-known absolute path using a filesystem stat call — no process is spawned. If the file is present, it is assumed to work and returned immediately:findWorkingPowershellViaProbing(): The originaltryFindWorkingCommand()probe logic is extracted into its own method. It is called both when the default path is absent and as the recovery path when the fast-path result is found to be broken at execution time.Automatic recovery in
installDotnet(): Thecp.execcall is wrapped in arunInstall(cmd, psRef, isRetry)inner helper. If the first execution attempt fails with cmd.exe-level "process not found" patterns in stderr (e.g.'powershell.exe' is not recognized as an internal or external command,The system cannot find the path specified) — indicating PowerShell itself could not be launched rather than the install script failing — the helper automatically callsfindWorkingPowershellViaProbing()to discover a working alternative and retries once.looksLikePowershellProcessNotFound(): New helper that distinguishes "PowerShell process itself couldn't launch" (cmd.exe-level errors) from "PowerShell ran but the install script failed" (PS-formatted errors), gating the recovery retry.For the common case — Windows with PowerShell at its default install location — the ~7s delay is replaced by a single near-instant
fs.statcall. Systems where the default path is absent or broken transparently fall back to full process-based validation and retry.Original prompt
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.