i'm banging my head against the evergreen problem of stdout and stderr redirection.
Small introduction
In powershell, you can do $p = Start-Process -Passthru -NoNewWindow ...
to start a windowless process and get a Process
object reference in $p
.
There are also a couple of arguments, -RedirectStandardOutput <path>
and -RedirectStandardError <path>
that effectively redirect the process' stdout/stderr to the files with the given <path>
s.
So, let's consider a simple program invocation, runnable both in cmd.exe
and pwsh.exe
, that generates both stdout and stderr: cmd /c "(ver & echo errrrr >&2)"
.
I want to get a reference to the process, so i do:
$p = Start-Process -PassThru -NoNewWindow cmd -ArgumentList '/c','(ver & echo errrrr >&2)' -RedirectStandardOutput 'c:\tmp\ver.txt' -RedirectStandardError 'c:\tmp\vererr.txt'
which is the same as running
& cmd /c '(ver & echo errrrr >&2)' >c:\tmp\ver.txt 2>c:\tmp\vererr.txt
BUT start-process
gets me a Process
object that i can store in $p
!
In any case both of these create ver.txt
and vererr.txt
with the corresponding streams' data (ver
=stdout, vererr
=stderr).
Question
My question is: how can i merge the program's entire output, then redirect it to a file, AND get a Process
object reference?
By "merge the entire output" i mean as when using >file 2>&1
:
cmd /c "(ver & echo errrrr >&2)" >c:\tmp\ver.txt 2>&1
This creates only the ver.txt
file with the invocation's full output.
The simple solution of specifying the same file with start-process
, yields an error:
PS > $p = start-process -PassThru cmd -ArgumentList '/c','(ver & echo errrrr >&2)' -RedirectStandardOutput 'c:\tmp\ver.txt' -RedirectStandardError 'c:\tmp\ver.txt'
start-process : This command cannot be run because "RedirectStandardOutput" and "RedirectStandardError" are same. Give different inputs and Run your command again.
At line:1 char:6
+ $p = start-process -PassThru cmd -ArgumentList '/c','(ver & echo errr …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
Is this even possible in powershell? Handmade solutions like these have deadlock and output order problems, meaning stdout and stderr data may appear NOT in order when outputting both of the streams to the same file: this might even be a .NET problem because even in pure C# i haven't found a reliable way to achieve this...