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 ?

Original source

Related problems