Ich versuche, ein Programm von PowerShell aus auszuführen, auf den Exit zu warten und dann auf den ExitCode zuzugreifen, aber ich habe nicht viel Glück. Ich möchte -Wait
Nicht zusammen mit Start-Process
verwenden, da ich im Hintergrund noch einige Verarbeitungsschritte ausführen muss.
Hier ist ein vereinfachtes Testskript:
cd "C:\Windows"
# ExitCode is available when using -Wait...
Write-Host "Starting Notepad with -Wait - return code will be available"
$process = (Start-Process -FilePath "notepad.exe" -PassThru -Wait)
Write-Host "Process finished with return code: " $process.ExitCode
# ExitCode is not available when waiting separately
Write-Host "Starting Notepad without -Wait - return code will NOT be available"
$process = (Start-Process -FilePath "notepad.exe" -PassThru)
$process.WaitForExit()
Write-Host "Process exit code should be here: " $process.ExitCode
Wenn Sie dieses Skript ausführen, wird Notepad gestartet. Nachdem dies manuell geschlossen wurde, wird der Beendigungscode gedruckt und ohne Verwendung von -wait
Erneut gestartet. Es wird kein ExitCode bereitgestellt, wenn dieser beendet wird:
Starting Notepad with -Wait - return code will be available
Process finished with return code: 0
Starting Notepad without -Wait - return code will NOT be available
Process exit code should be here:
Ich muss in der Lage sein, zwischen dem Starten des Programms und dem Warten auf das Beenden des Programms eine zusätzliche Verarbeitung durchzuführen, daher kann ich -Wait
Nicht verwenden. Wie kann ich das tun und trotzdem von diesem Prozess aus auf die .ExitCode-Eigenschaft zugreifen?
Zwei Dinge, die Sie tun könnten, denke ich ...
Hier ist, wie Sie entweder tun könnten:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "notepad.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = ""
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
#Do Other Stuff Here....
$p.WaitForExit()
$p.ExitCode
ODER
Start-Job -Name DoSomething -ScriptBlock {
& ping.exe somehost
Write-Output $LASTEXITCODE
}
#Do other stuff here
Get-Job -Name DoSomething | Wait-Job | Receive-Job
Hier sind zwei Dinge zu beachten. Zum einen das Argument -PassThru
Und zum anderen das Argument -Wait
. Sie müssen das wait-Argument wegen dieses Fehlers hinzufügen: http://connect.Microsoft.com/PowerShell/feedback/details/520554/start-process-does-not-return-exitcode-property
-PassThru [<SwitchParameter>]
Returns a process object for each process that the cmdlet started. By d
efault, this cmdlet does not generate any output.
Sobald Sie dies tun, wird ein Prozessobjekt zurückgegeben und Sie können die ExitCode-Eigenschaft dieses Objekts anzeigen. Hier ist ein Beispiel:
$process = start-process ping.exe -windowstyle Hidden -ArgumentList "-n 1 -w 127.0.0.1" -PassThru -Wait
$process.ExitCode
# This will print 1
Wenn Sie es ohne -PassThru
Oder -Wait
Ausführen, wird nichts gedruckt.
Dieselbe Antwort finden Sie hier: Wie führe ich ein Windows-Installationsprogramm aus und erhalte einen Erfolgs-/Fehlschlagswert in PowerShell?
Als ich den letzten Vorschlag oben ausprobierte, entdeckte ich eine noch einfachere Lösung. Alles, was ich tun musste, war das Prozesshandle zwischenzuspeichern. Sobald ich das getan habe, hat $ process.ExitCode richtig funktioniert. Wenn ich das Prozesshandle nicht zwischengespeichert habe, war $ process.ExitCode null.
beispiel:
$proc = Start-Process $msbuild -PassThru
$handle = $proc.Handle # cache proc.Handle
$proc.WaitForExit();
if ($proc.ExitCode -ne 0) {
Write-Warning "$_ exited with status code $($proc.ExitCode)"
}
Die Option "Warten" schien für mich zu blockieren, obwohl mein Prozess beendet war.
Ich habe versucht, Adrian Lösung und es funktioniert. Aber ich habe Wait-Process verwendet, anstatt mich auf einen Nebeneffekt beim Abrufen des Prozess-Handles zu verlassen.
So:
$proc = Start-Process $msbuild -PassThru
Wait-Process -InputObject $proc
if ($proc.ExitCode -ne 0) {
Write-Warning "$_ exited with status code $($proc.ExitCode)"
}
Oder füge dies hinzu ...
$code = @"
[DllImport("kernel32.dll")]
public static extern int GetExitCodeProcess(IntPtr hProcess, out Int32 exitcode);
"@
$type = Add-Type -MemberDefinition $code -Name "Win32" -Namespace Win32 -PassThru
[Int32]$exitCode = 0
$type::GetExitCodeProcess($process.Handle, [ref]$exitCode)
Mithilfe dieses Codes können Sie PowerShell weiterhin die Verwaltung umgeleiteter Ausgabe-/Fehlerströme überlassen, was mit System.Diagnostics.Process.Start () nicht direkt möglich ist.