Bangaio
Bangaio

Reputation: 265

Catching script-terminating errors only in PowerShell

PowerShell 5.1

I've written a wrapper script that launches another script, logs its output (via Start-Transcript), sends an email if it exited with a non-zero code, and finally rotates the log file based on file size.

I only want to catch errors that would cause the called script to exit when executed on its own. (Script-terminating term based on the discussion here: https://github.com/MicrosoftDocs/PowerShell-Docs/issues/1583).

try { 
    Invoke-Expression "& '$Script' $ArgList"
    $err = $LastExitCode
} catch { 
    Write-Error -ErrorRecord $_
    $err = 1
}

Catch this:

$ErrorActionPreference = 'Stop'
Remove-Item -Path DoesntExist

or this:

throw "Error"

But not this (script should continue executing as it would if not called via the logging script):

Test-Path -Foo bar

Is it possible? Or is there a better approach?

Upvotes: 0

Views: 697

Answers (1)

mklement0
mklement0

Reputation: 440162

A try { ... } catch { ... } statement makes no distinction between a statement-terminating (Test-Path -Foo bar) and a script-terminating error (throw "Error"): both sub-types of terminating errors trigger the catch block.

In other words: Any intrinsically statement-terminating error, such as 1 / 0 or Test-Path -Foo bar (an invocation-syntax error, because there is no such parameter) will invariably also trigger your catch block.

So will any non-terminating error that is promoted to a script-terminating one, either with $ErrorActionPreference = 'Stop' or -ErrorAction Stop (which is what you want).

  • As an aside: $ErrorActionPreference = 'Stop' - unlike -ErrorAction Stop - will also promote statement-terminating errors to script-terminating ones, which is just one of the problematic aspects of PowerShell's surprisingly complex error handling, discussed in detail in the GitHub docs issue linked to in your question.

Related information (which won't solve your problem):

With respect to post-mortem error analysis, the best you can do to analyze what kind of error occurred is to check if it was a script-terminating one triggered by a throw statement, by examining $_.Exception.WasThrownFromThrowStatement, but you won't generally be able to distinguish between a statement-terminating error, a non-terminating error, and a non-terminating error promoted to a script-terminating one.

GitHub issue #4781 discusses a potential future improvement for detecting the intrinsic vs. effective "fatality" of an error.

Upvotes: 1

Related Questions