4
votes

I have some powershell scripts with the following in them:

$ErrorActionPreference = "stop"
trap { Write-Error $_.Exception; }

When calling the script from a powershell window using a powershell redirection operator:

c:\somescript.ps1 2> c:\error.txt

It will only print out the error to the powershell window and not redirect it to the file. If I remove $ErrorActionPreference = "stop" from the script, then the redirection works, but that isn't a viable option since we need the scripts to terminate if it runs into any error. I've tried using '*>' too, but that produces the same results.

Is there any way to redirect the errors to a file without having to change all the scripts?

2

2 Answers

5
votes

The problem with your approach is that $ErrorActionPreference = "Stop":

  • instantly stops (aborts) the entire script and the command that calls it, c:\somescript.ps1 2> c:\error.txt,

  • which means that the redirection 2> c:\error.txt is not performed, and the error message displays in the console rather than being captured in the specified file.

The workaround is somewhat cumbersome:

Wrap the invocation of the other script in a try ... catch statement as follows:Tip of the hat to FatalBulletHit for his help.

$ErrorActionPreference = 'Stop'

try {

 c:\somescript.ps1

} catch {

  # Now you can write the error record to the file.
  $_ > c:\error.txt

  # == Optional additional actions.

  # If desired, you can additionally 
  # emit the error too (write it the error to the error stream).
  # !! -ErrorAction Continue is necessary in order to override
  # !! $ErrorActionPreference = 'Stop'.
  # !! Without it, the use of Write-Error itself would cause an - uncaught -
  # !! script-terminating (fatal) error. 
  Write-Error -ErrorRecord $_ -ErrorAction Continue

  # Exit the script with a nonzero exit code to signal failure
  # (which is useful if your script is called from *outside*
  # PowerShell).
  exit 1

}

The need to use -ErrorAction Continue (or temporarily set $ErrorActionPreference = 'Continue') before calling Write-Error in the catch block to avoid causing a script-terminating (fatal) error is surprising; it would also apply if your script / function is an advanced one and you used $PSCmdlet.WriteError($_) instead.

0
votes

You might want to have a look at using Try Catch Finally for Error Trapping.

I have had the most success with that.

Great TechNet Blog on this subject