0

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?

4
  • 2
    instead of define the $ErrorActionPreference variable, set it in the cmdlet, for example ignore the error for Test-Path -Foo bar -ErrorAction SilentlyContinue and use it for the Remove-Item -Path DoesntExist -ErrorAction Stop Commented Aug 29, 2021 at 11:23
  • 1
    I want the called script to behave like it would when executed on its own. In this example, Test-Path fails but the script keeps running. But when I call it via my wrapper script, it catches that exception and stops. Commented Aug 29, 2021 at 14:03
  • As an aside: Invoke-Expression (iex) should generally be avoided; definitely don't use it to invoke an external program or PowerShell script. Commented Aug 29, 2021 at 23:08
  • Thanks for the tip, I'll look into alternatives. Commented Aug 30, 2021 at 15:02

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.