Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process objects created with Start-Process -NoNewWindow and/or -RedirectStandard* never report their exit code on Windows. #5421

Closed
mklement0 opened this issue Nov 11, 2017 · 9 comments
Labels
Issue-Discussion the issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif Resolution-No Activity Issue has had no activity for 6 months or more WG-Cmdlets-Management cmdlets in the Microsoft.PowerShell.Management module

Comments

@mklement0
Copy link
Contributor

mklement0 commented Nov 11, 2017

Note:

Workaround:

Per #20716 (comment), the workaround is to cache the process handle before calling Wait-Process / .WaitForExit():

$p = Start-Process cmd -args '/c', 'ver' -PassThru -NoNewWindow
$dummy = $p.Handle # WORKAROUND: use a dummy variable to cache the handle
Wait-Process -id $p.Id
"Exit code: [$($p.ExitCode)]"  # Now the exit code is reported.

Steps to reproduce

On Windows:

$p = Start-Process cmd -args '/c', 'ver' -PassThru -NoNewWindow
Wait-Process -id $p.Id
"Exit code: [$($p.ExitCode)]"

Note that the problem only occurs when -NoNewWindows and /or any of the -RedirectStandard* parameters are present.

Inserting a $p.WaitForExit() call after the Wait-Process call, as suggested in the docs to ensure that .ExitCode has a value (which should be the equivalent of Wait-Process), doesn't help.

Expected behavior


Microsoft Windows [Version 10.0.15063]
Exit code: [0]

$ps.ExitCode should contain 0, given that the cmd command reports exit code 0.

Actual behavior


Microsoft Windows [Version 10.0.15063]
Exit code: []

Note how $ps.ExitCode is unexpectedly stringified to the empty string.
Also, even though Get-Member indicates that the property's date type is [int], $null -eq $ps.ExitCode is $true.

This suggests that an exception is occurring behind the scenes, which PowerShell quietly ignores.

An exception when accessing .ExitCode should only occur if the process hasn't exited yet, however, which is at odds with having used Wait-Process and $p.HasExited indicating $true.

Environment data

PowerShell Core v6.0.0-beta.9 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.674 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
@iSazonov iSazonov added WG-Cmdlets-Management cmdlets in the Microsoft.PowerShell.Management module Issue-Discussion the issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif labels Nov 11, 2017
@vexx32
Copy link
Collaborator

vexx32 commented Aug 27, 2018

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

Dug this up... Seems as though it's not so much waiting for it to end as it is explicitly querying for the process handle while it's still running is what allows the exit code to be captured.

Ideally, Start-Process could internally query the process handle from the object before passing it to the pipeline in order to ensure the exit code is always captured, regardless of the circumstance.

@mklement0
Copy link
Contributor Author

mklement0 commented Aug 27, 2018

Great find, @vexx32 - that sounds like a great workaround.

A little more background info to flesh out your statement, from a linked answer:

This is a quirk of the implementation of the .NET Process object. The implementation of the ExitCode property first checks if the process has exited.
For some reason, the code that performs that check not only looks at the HasExited property but also verifies that the process handle is present in the process object and throws an exception if it is not. PowerShell intercepts that exception and returns null.
Accessing the Handle property causes the process object to retrieve the process handle and store it internally. Once the handle is stored in the process object, the ExitCode property works as expected.

I wonder if there was ever a good reason for this behavior, or whether we should also file a CoreFx bug report.

@vexx32
Copy link
Collaborator

vexx32 commented Aug 27, 2018

It probably can't hurt, honestly. But meantime, we can temp-fix this fairly quickly, it would appear. 😄

I'm not familiar with the internals of that object, but I wouldn't be surprised if there was some weirdness where it accesses the ExitCode via the handle reference somehow, so if it isn't retrieved before the process exits, it can't get at it, or something.

Should still be fixed either way, heh.

@jmaxxz
Copy link

jmaxxz commented Jul 22, 2021

Any updates on this? This really should be addressed.

@jordanrh1
Copy link

Any update? This is a rather impactful productivity blocker because you can't tell if process succeeded or failed. Makes start-process pretty much useless.

@mklement0
Copy link
Contributor Author

Per #20716 (comment), the workaround (only applicable if -Wait isn't used) is to cache the process handle before calling Wait-Process / .WaitForExit(); I've also updated the initial post with an example.

@mklement0
Copy link
Contributor Author

@microsoft-github-policy-service microsoft-github-policy-service bot added the Resolution-No Activity Issue has had no activity for 6 months or more label Jun 11, 2024
Copy link
Contributor

This issue has not had any activity in 6 months, if there is no further activity in 7 days, the issue will be closed automatically.

Activity in this case refers only to comments on the issue. If the issue is closed and you are the author, you can re-open the issue using the button below. Please add more information to be considered during retriage. If you are not the author but the issue is impacting you after it has been closed, please submit a new issue with updated details and a link to this issue and the original.

@mklement0
Copy link
Contributor Author

It looks like the problem has indeed been fixed, as verified via the original repro steps, in the current version, v7.4.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Discussion the issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif Resolution-No Activity Issue has had no activity for 6 months or more WG-Cmdlets-Management cmdlets in the Microsoft.PowerShell.Management module
Projects
None yet
Development

No branches or pull requests

5 participants