Capturando errores y salidas estándar con Start-Process
¿Hay algún error en Start-Process
el comando de PowerShell al acceder a StandardError
yStandardOutput
propiedades
Si ejecuto lo siguiente no obtengo ningún resultado:
$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait
$process.StandardOutput
$process.StandardError
Pero si redirijo la salida a un archivo obtengo el resultado esperado:
$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait -RedirectStandardOutput stdout.txt -RedirectStandardError stderr.txt
Así Start-Process
fue diseñado por alguna razón. Aquí hay una manera de obtenerlo sin enviarlo al archivo:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "ping.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "localhost"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
En el código proporcionado en la pregunta, creo que debería funcionar leer la propiedad ExitCode de la variable de inicio.
$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait
$process.ExitCode
Tenga en cuenta que (como en su ejemplo) necesita agregar los parámetros -PassThru
y -Wait
(esto me sorprendió por un tiempo).
IMPORTANTE:
Hemos estado utilizando la función proporcionada anteriormente por LPG .
Sin embargo, esto contiene un error que puede encontrar al iniciar un proceso que genera muchos resultados. Debido a esto, podría terminar con un punto muerto al utilizar esta función. En su lugar, utilice la versión adaptada a continuación:
Function Execute-Command ($commandTitle, $commandPath, $commandArguments)
{
Try {
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $commandPath
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $commandArguments
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
[pscustomobject]@{
commandTitle = $commandTitle
stdout = $p.StandardOutput.ReadToEnd()
stderr = $p.StandardError.ReadToEnd()
ExitCode = $p.ExitCode
}
$p.WaitForExit()
}
Catch {
exit
}
}
Puede encontrar más información sobre este problema en MSDN :
Puede producirse una condición de interbloqueo si el proceso principal llama a p.WaitForExit antes de p.StandardError.ReadToEnd y el proceso secundario escribe suficiente texto para llenar la secuencia redirigida. El proceso padre esperaría indefinidamente a que saliera el proceso hijo. El proceso hijo esperaría indefinidamente a que el padre leyera el flujo completo de StandardError.