Redirecting output from an application linked with /SUBSYSTEM:WINDOWS with the > operator gives an empty file, even though piping to Out-File works and redirection works in CMD and Bash #25875
Replies: 5 comments 5 replies
|
There should not be an extra requirement on the application just because it uses For a GUI-subsystem application, make both redirection and waiting explicit: $process = Start-Process -FilePath '.\application.exe' `
-RedirectStandardOutput '.\file.log' `
-RedirectStandardError '.\error.log' `
-PassThru
$process.WaitForExit()Or, equivalently for this case: Start-Process -FilePath '.\application.exe' `
-RedirectStandardOutput '.\file.log' `
-RedirectStandardError '.\error.log' `
-Wait
Since the same executable and writes work under |
|
If you use GetFileType on the handle from GetStdHandle(STD_OUTPUT_HANDLE) in your windows app you should see that with file redirection under CMD.EXE you get a FILE_TYPE_DISK, but under both PowerShell.exe and pwsh.exe you get FILE_TYPE_PIPE. So under CMD.EXE it opened the file and gave the handle to the child process, where as PowerShell says here is a pipe, write your output and I will make sure it goes to the right place. It looks like the problem is that PowerShell is not waiting for end-of-file from reading the pipe before closing the file. But from PowerShell's point of view its unit of work was to launch the GUI program, not launch and wait for it to finish. That said, there are a few facts on the ground
I would like to stand back a little, and first ask if pipes and GUI programs should be supported at all. It is an edge case. Then I would suggest looking at all the uses cases for pipes and programs and see how they should work. Eg cmdlet | winapp | cmdlet etc, if you get the drift. How do the pipes work and what is the lifespan of each process? An observation I would make is the boundaries between components should be based on end-of-stream/end-of-file of the connecting pipes not the life-span of process at each stage. The only process you need to wait for is the one at the end of the pipeline, if it is not a GUI program and not redirected to another file. At the moment I would suggest that closing the file on a redirect should depend on reading until end-of-file from the source. If that effectively means waiting until the GUI process exits then so be it. The mechanism to determine that should be when ReadFile on the pipe returns zero length or error, not by WaitForSingleObject on the process. When the process ends there can still be unread bytes in the pipe. |
|
I feel like I'm probably replying to two robots but I'll reiterate the key point just in case there's a real human reading this.
If the problem were simply just that PowerShell always closed pipes as soon as it launched GUI apps or that the problem was intractable and nothing could ever be done about it, piping to |
|
Lol, no, well kind of… but I have not resolved or looked into the pipe issue yet. I DID push out another change and I think that’s what you saw…
From: Chris Djali ***@***.***>
Sent: Thursday, August 27, 2026 8:04 AM
To: PowerShell/PowerShell ***@***.***>
Cc: Kevin Komlosy ***@***.***>; Comment ***@***.***>
Subject: Re: [PowerShell/PowerShell] Redirecting output from an application linked with /SUBSYSTEM:WINDOWS with the > operator gives an empty file, even though piping to Out-File works and redirection works in CMD and Bash (Discussion #25875)
I feel like I'm probably replying to two robots but I'll reiterate the key point just in case there's a real human reading this.
application.exe | Out-File file.log works exactly the same for both /SUBSYSTEM:CONSOLE and /SUBSYSTEM:WINDOWS binaries, it's just application > file.log that shows a difference.
If the problem were simply just that PowerShell always closed pipes as soon as it launched GUI apps or that the problem was intractable and nothing could ever be done about it, piping to Out-File would be just as broken. As PowerShell is already giving a FILE_TYPE_PIPE when > is used, anything that relies on it being a FILE_TYPE_DISK is already broken, and wouldn't get any new symptoms from > being implemented by feeding the pipe to an implicit instance of the mechanism behind Out-File. The code already exists. The only novel bit would potentially by spinning it off into its own thread or subprocess so that control can be returned to the shell immediately.
—
Reply to this email directly, view it on GitHub<#25875?email_source=notifications&email_token=BOZIVJFJIM552XHNXIU3E3T5MAWV3A5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCOBRG42TSOBRUZZGKYLTN5XKOY3PNVWWK3TUUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#discussioncomment-18175981>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BOZIVJGZSFQHMRX4EZC3BPD5MAWV3AVCNFSNUABGKJSXA33TNF2G64TZHM2DSNRQHE2TQMJ3IRUXGY3VONZWS33OHM4DONJWG4ZDRILWAI>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://github.com/notifications/mobile/ios/BOZIVJFMTMMIP3PFIRSV4BL5MAWV3A5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCOBRG42TSOBRUZZGKYLTN5XKOY3PNVWWK3TUUVSXMZLOOSVGM33PORSXEX3JN5ZQ> and Android<https://github.com/notifications/mobile/android/BOZIVJHKYIHQWLL4D55RXYT5MAWV3A5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCOBRG42TSOBRUZZGKYLTN5XKOY3PNVWWK3TUUVSXMZLOOSXGM33PORSXEX3BNZSHE33JMQ>. Download it today!
You are receiving this because you commented.Message ID: ***@***.******@***.***>>
|

Uh oh!
There was an error while loading. Please reload this page.
Redirecting output from an application linked with
/SUBSYSTEM:WINDOWSwith the>operator (e.g.application.exe > file.log) always gives an empty file. Doing the same in CMD and Bash works just fine, and usingOut-File(e.g.application.exe | Out-File file.log) also works.From the application's perspective, the stdout handle appears to be a valid disk file, but data written to it doesn't appear in the file. The file's timestamp isn't updated after the application's launched, so I think that PowerShell is closing the file handle immediately instead of waiting until the application's exited like it would with
/SUBSYSTEM:CONSOLE. This wouldn't be a huge surprise as the prompt for the next command is printed immediately.Getting output to the console without using
/SUBSYSTEM:WINDOWScan be a bit of a pain and there are ways to do it badly that break redirection and pipes completely, but that's not what I'm discussing here. If you do nothing and don't manually attach to the parent console, redirection and pipelines work as described here, i.e. only pipes work in PowerShell and both pipes and redirection work in CMD and Bash. You get the same behaviour if you attach to the parent console properly (e.g. like https://gitlab.com/OpenMW/openmw/-/blob/master/components/debug/debugging.cpp?ref_type=heads#L47-101 by checking the file types of the handles).As CMD and Bash work, I'm inclined to think that this is a PowerShell bug, but maybe there's something extra that
/SUBSYSTEM:WINDOWSapplications are documented as needing to do in some obscure place that search engines don't find and the way CMD and MSYS2's Bash are written just happens to sidestep the requirement.All reactions