Stderr and stdout for powershell with Invoke-Expression has no output or errors
Note: The solution below assumes a well-behaved external utility: one that sends data to stdout, and error messages to stderr. If a given utility unexpectedly sends error messages to stdout instead, as appears to be the case for the OP, you must do your own parsing of stdout output to extract error messages.
$stdout = java -jar secretserver-jconsole.jar -s 123456 Password 2>($tmpFile=New-TemporaryFile)$stderr = Get-Content $tmpFile; Remove-Item $tmpFile
New-TemporaryFile
requires PSv5, but you can use [io.path]::GetTempFileName()
in earlier versions.
Note that both $stdout
and $stderr
will contain a string array, with each item representing an output line.
The external utility's exit code is reflected in PowerShell's automatic $LASTEXITCODE
variable.
Note that capturing stdout and stderr combined is actually easier:
$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1
Note: The stderr lines are each represented as a [System.Management.Automation.ErrorRecord]
instance in the result, but they evaluate to the contents of the line in a string context.
As for what you tried:
There's generally no need to store a command in a string (and therefore rarely a need to use Invoke-Expression
, whose use can be risky).
- Either: invoke even external command lines directly (be mindful of possibly unwanted interpretation of the command line by PowerShell; in PSv3,
--%
turns off PowerShell's interpretation - seeGet-Help about_Parsing
), - or, if you need to store the command in a variable first, use a script block (
$cmd = { ... }
), and invoke it later with&
(call operator) or.
(dot-sourcing operator) - the former creates a child scope for PS variables, the latter does not.
The -OutVariable
and -ErrorVariable
common parameters are only designed to work with PowerShell's output streams, not the outside world's stdout and stderr.
PowerShell captures stdout output as if it had been sent to PowerShell's success output stream, and treats the output lines as an array of strings.
Stderr output is passed through (and is not reflected in
$Error
), but you can redirect it to a file with2>$file
, or you can merge it into the success stream with2>&1
(in which case the stderr lines are each represented as a[System.Management.Automation.ErrorRecord]
instance).