2017-05-18 4 views
0

Das Powershell-Cmdlets Start-Process wirkt bizarr:

Wenn ich starte eine weitere Konsole Prozess und ich -NoNewWindow, die Exitcode-Eigenschaft angeben (ein int!) ist Null.

Hier ist ein Test: Gleich mit etwas anderem außer cmd. Dieser Test wurde auf einem Win10 mit PS5, es ist auch das gleiche mit Win7 und PS5:

PS C:\Users\Martin> cmd.exe /Cver 

Microsoft Windows [Version 10.0.15063] 
PS C:\Users\Martin> $PSVersionTable 

Name       Value 
----       ----- 
PSVersion      5.1.15063.296 
PSEdition      Desktop 
PSCompatibleVersions   {1.0, 2.0, 3.0, 4.0...} 
BuildVersion     10.0.15063.296 
CLRVersion      4.0.30319.42000 
WSManStackVersion    3.0 
PSRemotingProtocolVersion  2.3 
SerializationVersion   1.1.0.1 


PS C:\Users\Martin> $pNewWindow = Start-Process -FilePath "cmd.exe" -ArgumentList '/C"exit 42"' -PassThru 
PS C:\Users\Martin> $pNewWindow.WaitForExit() 
PS C:\Users\Martin> $pNoNewWindow.HasExited 
True 
PS C:\Users\Martin> $pNewWindow.ExitCode 
42 
PS C:\Users\Martin> $pNoNewWindow = Start-Process -FilePath "cmd.exe" -ArgumentList '/C"exit 42"' -PassThru -NoNewWindow 

PS C:\Users\Martin> $pNoNewWindow.WaitForExit() 
PS C:\Users\Martin> $pNoNewWindow.HasExited 
True 
PS C:\Users\Martin> $pNoNewWindow.ExitCode 
PS C:\Users\Martin> $pNoNewWindow.ExitCode -eq $null 
True 
PS C:\Users\Martin> $pNoNewWindow | Get-Member | ? {$_.Name -imatch "exit"} 


    TypeName: System.Diagnostics.Process 

Name  MemberType Definition 
----  ---------- ---------- 
Exited  Event  System.EventHandler Exited(System.Object, System.EventArgs) 
WaitForExit Method  bool WaitForExit(int milliseconds), void WaitForExit() 
ExitCode Property int ExitCode {get;} 
ExitTime Property datetime ExitTime {get;} 
HasExited Property bool HasExited {get;} 


PS C:\Users\Martin> 

... Also, das Eigentum ist da, aber es ist null, auch wenn es ein int ist?

+0

http://StackOverflow.com/Questions/10262231/BODAY-EXITCode-using-start-process-and-waitforexit-instead-for-wait –

+0

Ist das nicht ein Duplikat? – Matt

+0

@Matt - Ich würde es nicht zwangsläufig dupen, aber es ist sicher in der Nähe. Fühlen Sie sich frei zu wählen, wenn Sie es wertlos machen –

Antwort

0

Antwort von linked question ‚s Antwort des/Kommentar:

hatte, war zu tun, um den Prozess handle zwischenzuspeichern. Sobald ich das gemacht habe, hat $ process.ExitCode korrekt funktioniert. Wenn ich den Prozess-Handle nicht zwischenspeichern konnte, war $ process.ExitCode null.

und in der Tat für einen Prozess, die nicht sofort beenden (im Gegensatz zu den cmd.exe im Beispiel), die Abhilfe funktioniert:

$proc = Start-Process -NoNewWindow -PassThru ... 
$handle = $proc.Handle # cache proc.Handle https://stackoverflow.com/a/23797762/1479211 
$proc.WaitForExit() 
$proc.ExitCode ... will be set 

Ein Benutzer hinzugefügt, um eine Erklärung in die comments:

Dies ist eine Eigenart der Implementierung des Objekts .NET-Prozess. Die Implementierung der ExitCode-Eigenschaft überprüft zuerst, ob der Prozess beendet wurde. Aus irgendeinem Grund überprüft der Code, der diese Überprüfung durchführt, nicht nur die HasExited-Eigenschaft, sondern überprüft auch, ob der Prozesshandle im process-Objekt und throws an exception if it is not vorhanden ist. PowerShell fängt diese Ausnahme ab und gibt null zurück.

Der Zugriff auf die Eigenschaft Handle bewirkt, dass das Prozessobjekt den Prozesshandle und store it internally abruft. Sobald das Handle im Prozessobjekt gespeichert ist, funktioniert die ExitCode-Eigenschaft wie erwartet.

Da Start-Process kann keinen Prozess starten suspendiert, und der Griff kann nur so lange erhalten, wie der Prozess ausgeführt wird (es erscheint), ist die Verwendung ein wenig spröde für Kurz laufenden Prozesse.

Verwandte Themen