2017-05-18 7 views
0

L'applet de commande Powershell Start-Process est agit bizarrement:

Quand je lance un autre processus de la console et je précise -NoNewWindow, la propriété ExitCode (un int!) est nul.

Voici un test: Même chose avec autre chose que cmd. Ce test a été sur un Win10 avec PS5, il est aussi la même chose avec Win7 et 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> 

... Ainsi, la propriété est là, mais il est null, même si elle est un int?

+0

http://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait –

+0

N'est-ce pas un doublon alors? – Matt

+0

@Matt - Je ne voudrais pas nécessairement dupe mais il est certainement proche. Ne hésitez pas à voter si dupeing il ajoute de la valeur pour vous –

Répondre

0

Réponse de/commentaire de réponse de linked question:

avait à faire était de mettre en cache la poignée processus. Dès que j'ai fait cela, $ process.ExitCode a fonctionné correctement. Si je n'ai pas mis en cache le handle de processus, $ process.ExitCode était null.

et en effet, pour un processus qui ne le fait pas immédiatement fin (contrairement à la cmd.exe dans l'exemple), la solution de contournement fonctionne:

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

Un utilisateur a ajouté une explication le comments:

Ceci est une anomalie de l'implémentation de l'objet .NET Process. L'implémentation de la propriété ExitCode vérifie d'abord si le processus s'est terminé. Pour une raison quelconque, le code qui effectue cette vérification non seulement regarde la propriété HasExited mais vérifie également que le handle de processus est présent dans l'objet de processus et throws an exception if it is not. PowerShell intercepte cette exception et renvoie null.

L'accès à la propriété Handle entraîne l'objet de processus à récupérer le handle de processus et store it internally. Une fois que le handle est stocké dans l'objet de processus, la propriété ExitCode fonctionne comme prévu.

Depuis Start-Process ne peut pas lancer un processus suspendu, et la poignée ne peut être obtenue tant que le processus est en cours (il semble), l'utilisation est un peu fragile pour les processus en cours d'exécution court.