From cf55ade92a5c0388663742880280191956ee16a8 Mon Sep 17 00:00:00 2001 From: Greg Joseph Date: Tue, 30 Jun 2026 11:45:03 -0700 Subject: [PATCH] fix(validation): launch sample processes via executable shim on Windows Resolve-CommandPath returned the highest-precedence Get-Command match, which on Windows is the PowerShell script shim (e.g. npx.ps1). Start- LoggedProcess passes that path to Start-Process with output redirection, forcing the CreateProcess code path -- which cannot execute .ps1 (or the extensionless npm/npx) shims. Every Windows runtime/browser smoke step therefore failed immediately with "%1 is not a valid Win32 application". Resolve a directly executable form (.cmd/.exe/...) when one exists, while falling back to the Application command form for Linux/macOS, where the shebang executable can be exec'd directly. The call operator path (Invoke-ExternalCommand) is unaffected since it runs .cmd shims fine too. Verified on Windows (pwsh 7.4): Resolve-CommandPath now returns npx.cmd / npm.cmd / node.exe; Start-LoggedProcess launches with redirection without error; and project-management/validate-sample.ps1 reaches and passes the preview-server startup it previously crashed on (exit code 0). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Tools/powershell/SampleValidation.ps1 | 33 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Tools/powershell/SampleValidation.ps1 b/Tools/powershell/SampleValidation.ps1 index f215afa..127abe8 100644 --- a/Tools/powershell/SampleValidation.ps1 +++ b/Tools/powershell/SampleValidation.ps1 @@ -30,12 +30,37 @@ function Resolve-CommandPath { return $Name } - $command = Get-Command $Name -ErrorAction Stop - if ($null -ne $command.Source -and $command.Source.Length -gt 0) { - return $command.Source + $commands = @(Get-Command $Name -All -ErrorAction Stop) + + # Start-LoggedProcess launches commands through Start-Process, which (when output is + # redirected) uses the OS CreateProcess API. CreateProcess cannot execute PowerShell + # script shims (.ps1) and, on Windows, cannot execute the extensionless shell-script + # shims that npm/npx ship. Get-Command returns the .ps1 shim first by precedence, so + # prefer a directly executable form (.cmd/.exe/...) that both the call operator and + # Start-Process can launch. + $executableExtensions = @('.exe', '.cmd', '.bat', '.com') + + $preferred = $commands | Where-Object { + $_.CommandType -eq 'Application' -and + $_.Source -and + $executableExtensions -contains [System.IO.Path]::GetExtension($_.Source).ToLowerInvariant() + } | Select-Object -First 1 + + if ($null -eq $preferred) { + # On non-Windows platforms the Application form is typically an extensionless + # executable or a shebang script that CreateProcess can exec directly. + $preferred = $commands | Where-Object { $_.CommandType -eq 'Application' } | Select-Object -First 1 } - return $command.Name + if ($null -eq $preferred) { + $preferred = $commands | Select-Object -First 1 + } + + if ($null -ne $preferred.Source -and $preferred.Source.Length -gt 0) { + return $preferred.Source + } + + return $preferred.Name } function Invoke-ExternalCommand {