Capturando errores y salidas estándar con Start-Process

Resuelto jzbruno asked hace 12 años • 12 respuestas

¿Hay algún error en Start-Processel comando de PowerShell al acceder a StandardErroryStandardOutput 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
jzbruno avatar Jan 07 '12 00:01 jzbruno
Aceptado

Así Start-Processfue 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
Andy Arismendi avatar Jan 06 '2012 17:01 Andy Arismendi

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 -PassThruy -Wait(esto me sorprendió por un tiempo).

JJones avatar Dec 11 '2014 10:12 JJones

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.

pserranne avatar Mar 24 '2017 09:03 pserranne