it-swarm.com.de

Standardausgabe und Fehler mit Start-Prozess erfassen

Gibt es einen Fehler im Start-Process-Befehl von PowerShell beim Zugriff auf die Eigenschaften StandardError und StandardOutput?

Wenn ich folgendes ausführe, erhalte ich keine Ausgabe:

$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait
$process.StandardOutput
$process.StandardError

Wenn ich die Ausgabe jedoch in eine Datei umleiten, erhalte ich das erwartete Ergebnis:

$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait -RedirectStandardOutput stdout.txt -RedirectStandardError stderr.txt
83
jzbruno

So wurde Start-Process aus irgendeinem Grund entworfen. So erhalten Sie es, ohne es an eine Datei zu senden:

$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
104
Andy Arismendi

In dem in der Frage angegebenen Code denke ich, dass das Lesen der ExitCode-Eigenschaft der Initiierungsvariablen funktionieren sollte.

$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait
$process.ExitCode

Beachten Sie, dass Sie (wie in Ihrem Beispiel) die Parameter -PassThru und -Wait hinzufügen müssen (dies hat mich eine Weile erwischt).

14
JJones

Ich hatte auch dieses Problem und endete mit Andys Code , um eine Funktion zu erstellen, um Dinge zu löschen, wenn mehrere Befehle ausgeführt werden müssen.

Es werden stderr, stdout und Beendigungscodes als Objekte zurückgegeben. Eine Sache zu beachten: Die Funktion akzeptiert .\ im Pfad nicht; Es müssen vollständige Pfade verwendet werden.

Function Execute-Command ($commandTitle, $commandPath, $commandArguments)
{
    $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
    $p.WaitForExit()
    [pscustomobject]@{
        commandTitle = $commandTitle
        stdout = $p.StandardOutput.ReadToEnd()
        stderr = $p.StandardError.ReadToEnd()
        ExitCode = $p.ExitCode
    }
}

So verwenden Sie es:

$DisableACMonitorTimeOut = Execute-Command -commandTitle "Disable Monitor Timeout" -commandPath "C:\Windows\System32\powercfg.exe" -commandArguments " -x monitor-timeout-ac 0"
9
LPG

Ich hatte wirklich Probleme mit diesen Beispielen von Andy Arismendi und von LPG . Sie sollten immer verwenden:

$stdout = $p.StandardOutput.ReadToEnd()

vor dem anrufen

$p.WaitForExit()

Ein vollständiges Beispiel ist:

$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
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
$p.WaitForExit()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
6
Rainer

WICHTIG:

Wir haben die Funktion wie oben von LPG vorgesehen verwendet.

Dies enthält jedoch einen Fehler, auf den Sie möglicherweise stoßen, wenn Sie einen Prozess starten, der viele Ausgaben generiert. Daher kann es bei Verwendung dieser Funktion zu einem Deadlock kommen. Verwenden Sie stattdessen die angepasste Version:

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
  }
}

Weitere Informationen zu diesem Problem finden Sie unter unter MSDN :

Eine Deadlock-Bedingung kann zur Folge haben, wenn der übergeordnete Prozess p.WaitForExit vor p.StandardError. Der übergeordnete Prozess würde unendlich lange warten, bis der untergeordnete Prozess beendet wurde. Der untergeordnete Prozess würde auf unbestimmte Zeit warten, bis das übergeordnete Element den vollständigen StandardError-Stream lesen kann.

4
pserranne

Hier ist meine Version der Funktion, die den Standard System.Diagnostics.Process mit 3 neuen Eigenschaften zurückgibt

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.WindowStyle = 'Hidden'
        $pinfo.CreateNoWindow = $True
        $pinfo.Arguments = $commandArguments
        $p = New-Object System.Diagnostics.Process
        $p.StartInfo = $pinfo
        $p.Start() | Out-Null
        $stdout = $p.StandardOutput.ReadToEnd()
        $stderr = $p.StandardError.ReadToEnd()
        $p.WaitForExit()
        $p | Add-Member "commandTitle" $commandTitle
        $p | Add-Member "stdout" $stdout
        $p | Add-Member "stderr" $stderr
    }
    Catch {
    }
    $p
}
0
Anabela Mazurek

Hier ist eine einfache Möglichkeit, die Ausgabe eines anderen Powershell-Prozesses abzurufen:

start-process -wait -nonewwindow powershell 'ps | Export-Clixml out.xml'; import-clixml out.xml
0
js2010