Use cmd-based redirection in scratch runner

This commit is contained in:
master
2026-03-13 13:59:00 +02:00
parent 024b162b55
commit 6954ac7967

View File

@@ -78,6 +78,8 @@ function Invoke-External {
) )
Push-Location $WorkingDirectory Push-Location $WorkingDirectory
$stdoutPath = New-LogCapturePath -Suffix '.stdout.log'
$stderrPath = New-LogCapturePath -Suffix '.stderr.log'
try { try {
$resolvedFilePath = $FilePath $resolvedFilePath = $FilePath
if (Test-Path $FilePath) { if (Test-Path $FilePath) {
@@ -93,76 +95,44 @@ function Invoke-External {
$startArgumentList = @('-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $resolvedFilePath) + @($ArgumentList) $startArgumentList = @('-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $resolvedFilePath) + @($ArgumentList)
} }
$startInfo = [System.Diagnostics.ProcessStartInfo]::new() $commandLine = (@((Format-ProcessArgument -Value $startFilePath)) + @($startArgumentList | ForEach-Object { Format-ProcessArgument -Value ([string]$_) })) -join ' '
$startInfo.FileName = $startFilePath $redirectedCommand = '{0} 1>{1} 2>{2}' -f $commandLine, (Format-ProcessArgument -Value $stdoutPath), (Format-ProcessArgument -Value $stderrPath)
$startInfo.Arguments = (($startArgumentList | ForEach-Object { Format-ProcessArgument -Value ([string]$_) }) -join ' ') $cmdPath = (Get-Command cmd.exe -ErrorAction Stop).Source
$startInfo.WorkingDirectory = $WorkingDirectory $cmdArguments = @('/d', '/s', '/c', $redirectedCommand)
$startInfo.UseShellExecute = $false
$startInfo.RedirectStandardOutput = $true
$startInfo.RedirectStandardError = $true
$process = [System.Diagnostics.Process]::new() $process = Start-Process `
$process.StartInfo = $startInfo -FilePath $cmdPath `
-ArgumentList $cmdArguments `
-WorkingDirectory $WorkingDirectory `
-PassThru
$stdoutQueue = [System.Collections.Concurrent.ConcurrentQueue[string]]::new() $stdoutIndex = 0
$stderrQueue = [System.Collections.Concurrent.ConcurrentQueue[string]]::new() $stderrIndex = 0
$stdoutHandler = [System.Diagnostics.DataReceivedEventHandler]{
param($sender, $eventArgs)
if ($null -ne $eventArgs.Data) {
$stdoutQueue.Enqueue($eventArgs.Data)
}
}
$stderrHandler = [System.Diagnostics.DataReceivedEventHandler]{
param($sender, $eventArgs)
if ($null -ne $eventArgs.Data) {
$stderrQueue.Enqueue($eventArgs.Data)
}
}
$process.add_OutputDataReceived($stdoutHandler)
$process.add_ErrorDataReceived($stderrHandler)
if (-not $process.Start()) {
throw "Failed to start process: $resolvedFilePath"
}
$process.BeginOutputReadLine()
$process.BeginErrorReadLine()
$dequeuedLine = $null
while (-not $process.HasExited) { while (-not $process.HasExited) {
while ($stdoutQueue.TryDequeue([ref]$dequeuedLine)) { Write-LogCaptureDelta -Path $stdoutPath -LineIndex ([ref]$stdoutIndex)
$dequeuedLine | Out-Host Write-LogCaptureDelta -Path $stderrPath -LineIndex ([ref]$stderrIndex)
$dequeuedLine = $null
}
while ($stderrQueue.TryDequeue([ref]$dequeuedLine)) {
$dequeuedLine | Out-Host
$dequeuedLine = $null
}
Start-Sleep -Milliseconds 500 Start-Sleep -Milliseconds 500
$process.Refresh()
} }
$process.WaitForExit() $process.WaitForExit()
$process.Refresh()
while ($stdoutQueue.TryDequeue([ref]$dequeuedLine)) { Write-LogCaptureDelta -Path $stdoutPath -LineIndex ([ref]$stdoutIndex)
$dequeuedLine | Out-Host Write-LogCaptureDelta -Path $stderrPath -LineIndex ([ref]$stderrIndex)
$dequeuedLine = $null
}
while ($stderrQueue.TryDequeue([ref]$dequeuedLine)) {
$dequeuedLine | Out-Host
$dequeuedLine = $null
}
if ($process.ExitCode -ne 0) { if ($process.ExitCode -ne 0) {
throw "Command failed: $resolvedFilePath $($ArgumentList -join ' ')" throw "Command failed: $resolvedFilePath $($ArgumentList -join ' ')"
} }
} }
finally { finally {
foreach ($capturePath in @($stdoutPath, $stderrPath)) {
if (Test-Path $capturePath) {
Remove-Item $capturePath -Force -ErrorAction SilentlyContinue
}
}
Pop-Location Pop-Location
} }
} }