'BinSkim.exe' = @((Join-Path $BinSkimDir 'BinSkim.exe'))
'rsync.exe' = @((Join-Path $RsyncDir 'rsync.exe'))
'ssh.exe' = @((Join-Path $env:WINDIR 'System32\OpenSSH\ssh.exe'))
- 'nasm.exe' = @()
+ # NASM's installer falls back to a per-user directory when it cannot
+ # write to Program Files - see the NASM comment in setup-windows.bat. It
+ # registers nothing there, so winget cannot see it (and re-downloads and
+ # re-runs the installer on every run), and it puts nothing on the PATH.
+ # Without these candidates the audit reported "- not installed" for a
+ # nasm.exe that was on disk all along, and then still concluded that
+ # everything had resolved.
+ 'nasm.exe' = @(
+ (Join-Path $env:LOCALAPPDATA 'bin\NASM\nasm.exe')
+ (Join-Path $env:ProgramFiles 'NASM\nasm.exe')
+ (Join-Path ${env:ProgramFiles(x86)} 'NASM\nasm.exe')
+ )
'iperf3.exe' = @()
'OpenCppCoverage.exe' = @((Join-Path $env:ProgramFiles 'OpenCppCoverage\OpenCppCoverage.exe'), (Join-Path ${env:ProgramFiles(x86)} 'OpenCppCoverage\OpenCppCoverage.exe'))
'vswhere.exe' = @($vsWhereExe)
# $global:LASTEXITCODE is cleared first because an exe that cannot start at\r
# all throws without setting one, and the stale 0 from the previous native\r
# command would otherwise read as success.\r
+ #\r
+ # DRAIN THE OUTPUT BEFORE READING $LASTEXITCODE. `... | Select-Object -First 1`\r
+ # was the original spelling here, and it is a trap: Select-Object stops the\r
+ # pipeline the instant it has its one object, and that is when ssh.exe has\r
+ # WRITTEN its banner - not when it has exited. PowerShell then tears the\r
+ # pipeline down, kills the still-running process, and reports -1. Measured on a\r
+ # healthy binary on an x64 box: 24 of 25 runs reported exit -1 through\r
+ # Select-Object, and 25 of 25 reported 0 when the output was collected first.\r
+ #\r
+ # So this check was deleting a perfectly good ssh.exe on almost every run, on\r
+ # every architecture, and the resulting fallback to the in-box client - the\r
+ # ~17MB/s one this whole step exists to avoid - looked like a property of the\r
+ # release rather than a bug in the test. Collect, THEN take the first line.\r
$SshExe = Join-Path $RsyncDir 'ssh.exe'\r
if ($WantSsh -and (Test-Path $SshExe)) {\r
$prevEap = $ErrorActionPreference\r
$ErrorActionPreference = 'Continue'\r
$global:LASTEXITCODE = $null\r
$sshVer = $null\r
- try { $sshVer = (& $SshExe -V 2>&1 | Select-Object -First 1) } catch { }\r
+ try { $sshOut = (& $SshExe -V 2>&1); $sshVer = $sshOut | Select-Object -First 1 } catch { }\r
finally { $ErrorActionPreference = $prevEap }\r
if ($LASTEXITCODE -eq 0) {\r
Write-Host " ssh.exe runs: $sshVer"\r