PowerShell – redirect executable’s stderr to file or variable but still have stdout go to console

Question:

I’m writing a script to download several repositories from GitHub. Here is the command to download a repository:

When I run this command it displays some nice progress information in the console window that I want displayed.

The problem is that I also want to be able to detect if any errors have occurred while downloading. I found this post that talks about redirecting the various streams, so I tried:

This pipes any errors from stderr to my file, but no longer displays the nice progress information in the console.

I can use the Tee-Object like so:

and I still get the nice progress output, but this pipes stdout to the file, not stderr; I’m only concerned with detecting errors.

Is there a way that I can store any errors that occur in a file or (preferably) a variable, while also still having the progress information piped to the console window? I have a feeling that the answer might lie in redirecting various streams into other streams as discusses in this post, but I’m not really sure.

======== Update =======

I’m not sure if the git.exe is different than your typical executable, but I’ve done some more testing and here is what I’ve found:

$output always contains the text “Cloning into ‘[localRepoDirectory]’…”, whether the command completed successfully or produced an error. Also, the progress information is still written to the console when doing this. This leads me to think that the progress information is not written via stdout, but by some other stream?

If an error occurs the error is written to the console, but in the usual white foreground color, not the typical red for errors and yellow for warnings. When this is called from within a cmdlet function and the command fails with an error, the error is NOT returned via the function’s -ErrorVariable (or -WarningVariable) parameter (however if I do my own Write-Error that does get returned via -ErrorVariable). This leads me to think that git.exe doesn’t write to stderr, but when we do:

The error message is written to the file, so that makes me think that it does write to stderr. So now I’m confused…

======== Update 2 =======

So with Byron’s help I’ve tried a couple of more solutions using a new process, but still can’t get what I want. When using a new process I never get the nice progress written to the console.

The three new methods that I’ve tried both use this bit of code in common:

Method 1 – Run in new process and read output afterwards:

Method 2 – Get output synchronously:

Even though this looks like it would write the output while the process is running, it doesn’t write anything until after the process exits.

Method 3 – Get output asynchronously:

This does output data while the process is working which is good, but it still doesn’t display the nice progress information 🙁

Answer:

I think I have your answer. I’m working with PowerShell for a while and created several build systems. Sorry if the script is a bit long, but it works.

The log file must be in the global scope because the routine which runs the event processing is not in the script scope.

Sample of my log file:

Out – Cloning into ”…
ERROR – Checking out files: 22% (666/2971)
ERROR – Checking out files: 23% (684/2971)
ERROR – Checking out files: 24% (714/2971)

Source:

PowerShell – redirect executable’s stderr to file or variable but still have stdout go to console by licensed under CC BY-SA | With most appropriate answer!

Leave a Reply