Start-Process / System.Diagnostics.Process ExitCode is $null with -NoNewWindow

Viewed 2093

The Powershell cmdlet Start-Processis acting weirdly:

When I launch another console process and I specify -NoNewWindow, the ExitCode property (an int!) is null.

Here's a test: Same with something else besides cmd. This test was on a Win10 with PS5, it is also the same with Win7 and 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>

... So, the Property is there, but it's null, even though it's an int?

2 Answers

We encountered a similar issue in our Environment. While executing the following command:

Start-Process -FilePath C:\Windows\system32\reg.exe -PassThru -Wait -NoNewWindow

or

Start-Process -FilePath C:\Windows\system32\reg.exe -PassThru -Wait -WindowStyle Hidden

As stated by Martin Ba, it seems like the started Process (reg.exe) has stopped before Start-Process was able to get a Handle from the Process.

Using -Wait or .WaitForExit() does not make a difference because both Methods check if the process has exited. If it did Exit, PowerShell won't be able to get the necessary handle for the Process. The Handle is necessary because it holds the ExitCode of the started Process.

The following error is thrown, if the Process has already exited:

System.Management.Automation.CmdletInvocationException: Cannot process request because the process (<ProcessIdHere>) has exited. ---> 
System.InvalidOperationException: Cannot process request because the process (<ProcessIdHere>) has exited.
  at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited) 
  at System.Diagnostics.Process.OpenProcessHandle(Int32 access) 
  at System.Diagnostics.Process.get_Handle()

Using -WindowStyle Hidden instead of -NoNewWindow may reduce how often the error occurs. This is because -WindowStyle Hidden is creating a new Shell (--> more Overhead), whereas -NoNewWindow uses the current Shell.

We created a UserVoice entry for this issue. Maybe the PowerShell Team is able to work around this behavior: https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/35737357--bug-start-process-might-not-return-handle-exitco

Related