PowerShell: Manage errors with Invoke-Expression
powershell
Solution
I was going crazy trying to make capturing the STDERR stream to a variable work. I finally solved it. There is a quirk in the invoke-expression command that makes the whole 2&>1 redirect fail, but if you omit the 1 it does the right thing.
function runDOScmd($cmd, $cmdargs)
{
# record the current ErrorActionPreference
$ep_restore = $ErrorActionPreference
# set the ErrorActionPreference
$ErrorActionPreference="SilentlyContinue"
# initialize the output vars
$errout = $stdout = ""
# After hours of tweak and run I stumbled on this solution
$null = iex "& $cmd $cmdargs 2>''" -ErrorVariable errout -OutVariable stdout
<# these are two apostrophes after the >
From what I can tell, in order to catch the stderr stream you need to try to redirect it,
the -ErrorVariable param won't get anything unless you do. It seems that powershell
intercepts the redirected stream, but it must be redirected first.
#>
# restore the ErrorActionPreference
$ErrorActionPreference=$ep_restore
# I do this because I am only interested in the message portion
# $errout is actually a full ErrorRecord object
$errrpt = ""
if($errout)
{
$errrpt = $errout[0].Exception
}
# return a 3 member arraylist with the results.
$LASTEXITCODE, $stdout, $errrpt
}
Problem
I try to figure how to determine if a command throw with Invoke-Expression fail. Even the variable $?, $LASTEXITCODE or the -ErrorVariable don't help me. For example : `PS C:\> $cmd="cat c:\xxx.txt"` Call $cmd with Invoke-Expression `PS C:\> Invoke-Expression $cmd -ErrorVariable err` `Get-Content : Cannot find path 'C:\xxx.txt' because it does not exist.` `At line:1 char:4` `+ cat <<<< c:\xxx.txt + CategoryInfo : ObjectNotFound: (C:\xxx.txt:String) [Get-Content], ItemNotFoundExcep tion + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand` The $? is True `PS C:\> $?` `True` The $LASTEXITCODE is 0 `PS C:\> $LASTEXITCODE` `0` And the $err is empty `PS C:\> $err` `PS C:\>` The only way I found is to redirect STD_ERR in a file and test if this file is empty `PS C:\> Invoke-Expression $cmd 2>err.txt` `PS C:\> cat err.txt` Get-Content : Cannot find path 'C:\xxx.txt' because it does not exist. At line:1 char:4 + cat <<<< c:\xxx.txt + CategoryInfo : ObjectNotFound: (C:\xxx.txt:String) [Get-Content], ItemNotFoundExcep tion + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand Is it the only and best way to do this ?