I\'m trying to get my script to stop if it hits an error, and use try... catch to give me an easy way to handle the error. The easiest thing in the world I\'d have thought,
The whole idea of a try/catch control is that you tell the script what to do if it encounters a terminating error, instead of the default action of throwing the error and stopping the script. If your catch block just displays a message to the terminal with Write-Host, that's all the error handling there will be, and the script will continue from there. If you think about it, it would partially defeat the purpose of try/catch if the script were stopped automatically whenever an error is caught.
In the catch block, $_ will be set to the ErrorRecord object representing the terminating error from the try block (the same one that gets stored in $error[0]). So the simplest way to end the script is to rethrow the error that would have been thrown if you hadn't used a try/catch:
try {
Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
# Custom action to perform before terminating
throw $_
}
Or, if you want to display a custom message instead of the default ErrorRecord:
try {
Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
throw 'Custom error message'
}
Or you could use break as suggested in Joost's answer if you want to just quit after you're finished with your custom error handling without throwing an error to the error stream.
Or you could get more sophisticated and create your own ErrorRecord object. There's a lot you can do with that, it's too big a topic to cover comprehensively here, but you can get more info about the syntax by googling System.Management.Automation.ErrorRecord. Here's an example from one of my scripts to get you started (from a function that executes a SQL query defined in the $query variable against a SQL Server database):
} catch {
$ErrorRecord = New-Object System.Management.Automation.ErrorRecord(
(New-Object Exception("Exception executing the query: $($_.Exception.InnerException.Message)")),
$query,
[System.Management.Automation.ErrorCategory]::InvalidArgument,
$null
)
$ErrorRecord.CategoryInfo.Reason = $_.CategoryInfo.Reason;
$ErrorRecord.CategoryInfo.Activity = $_.InvocationInfo.InvocationName;
$PSCmdlet.ThrowTerminatingError($ErrorRecord);
}
A couple of notes:
[CmdletBinding()]
at the beginning of the function or script. Otherwise, you can just use throw $ErrorRecord
to throw your custom error. However, the result will be more Cmdlet-style if you use $PSCmdlet.ThrowTerminatingError. (throw will spit back the line from the function that generated the error, whereas $PSCmdlet.ThrowTerminatingError will give you the line from the calling context where the function was used. It's hard to describe in a way that makes sense without getting too elaborate, but if you experiment with it you'll see what I mean.)BTW, it's redundant to set $ErrorActionPreference = "Stop"
, and then use -ErrorAction Stop
. The preference variable sets the default action for all cmdlets, and the -ErrorAction switch overrides the default action for a particular cmdlet, so there's no need to first specify the default, then use -ErrorAction to specify the same action you just set as the default. What you probably want to do is just leave out $ErrorActionPreference = "Stop"
.