This is a best practice question I suppose.
When designing functions that will be used within scripts, what is the best way to handle errors that could occur within the function?
For example, say we have a basic function that does X and Y:
Function Test-Function
{
Try
{
<# Something in here that would generate an error #>
}
Catch
{
Throw
}
Return $someReturnResultIWantInMyScript
}
My script calls this function:
Try
{
$ValueIWantFromFunction = Test-Function
}
Catch
{
<# Do something here #>
}
If the Test-Function
hits a terminating error, it will throw to the caller. The Try/Catch
around my function call in the script will receive this error and hit its own catch. I can then decide what to do.
If I didn't throw an error within the function, the script wouldn't see the terminating error, and then my $ValueIWantFromFunction
could contain $Null
or something not useful.
Is this a good way of error handling with functions and function calls within scripts? Is there a better way?
Use the try block to define a section of a script in which you want PowerShell to monitor for errors. When an error occurs within the try block, the error is first saved to the $Error automatic variable. PowerShell then searches for a catch block to handle the error.
The “$_” is said to be the pipeline variable in PowerShell. The “$_” variable is an alias to PowerShell's automatic variable named “$PSItem“. It has multiple use cases such as filtering an item or referring to any specific object.
The above error is generated by cmdlet and it is a non-terminating error. You can handle both the terminating and non-terminating error (by converting them into terminating error) using ErrorAction cmdlet, $ErrorActionPreference variable and try, catch, and finally blocks.
As a best practice, I like to use exceptions to handle errors in my functions/scripts and document them so the caller knows what went wrong. For example:
Function Remove-File
{
[CmdletBinding()]
[OutputType([Int])]
Param(
[Parameter(Mandatory)]
[String]$Path
)
Try
{
Remove-Item -Path $Path
Return 0
}
Catch
{
Return 1
}
}
If I'm designing my own function/cmdlet, I'll generate a custom [ErrorRecord]
object to be thrown:
#Requires -Version 5
If ($ErrorCondition)
{
$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
[System.Exception]::new('Error message'),
'FullyQualifiedName',
[System.Management.Automation.ErrorCategory]::DeviceError,
$ErrorCausingObject
)
)
}
Using this method, I can include in the documentation which errors get thrown depending on what went wrong so the caller can utilize multiple catches depending on the thrown error and handle it.
Here are some nice articles:
Everything about exceptions
Scripting Guy: Handling errors
On the OutputType attribute
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With