Despite being a great language, PowerShell is not impervious to errors. Errors that occur within your code can stop it’s execution or even cause unexpected changes in the resources that your script is managing. Learning to handle these errors gracefully is the foundation of defensive coding. Today, we’ll take a quick look at how PowerShell handles errors with Try-Catch-Finally blocks. They allow you to gracefully handle errors and perform cleanup operations, ensuring that your script doesn’t crash when the unexpected occurs. We’ll then cover the differences in terminating and non-terminating errors and why you should take these into consideration when implementing error handling.
The Try Block Link to heading
The Try block is where you place the code that might generate an error. Think of it as a protective bubble around your potentially troublesome code. If an error occurs within the Try block, PowerShell will immediately jump to the corresponding Catch block.
Here’s a simple example:
try {
# Code that might generate an error
Get-Item -Path "NonexistentFile.txt"
}
catch {
# Code to handle the error
Write-Host "An error occurred: $_"
}
The Catch Block Link to heading
The Catch block is where you can handle the error. PowerShell provides you with a special variable $_ that contains information about the error. You can use this variable to display error messages or even take corrective actions.
In the example above, we’re capturing the error generated by attempting to retrieve a nonexistent file. The $_ variable holds the error message, which we’re displaying using Write-Host.
The Finally Block Link to heading
Now, let’s talk about the unsung hero – the Finally block. This block is executed regardless of whether an error occurred or not. It’s where you can place cleanup code that ensures your script leaves no trace behind, even in the face of adversity. Some tasks that are commonly done in the finally block are closing database connections, removing temp files, etc. The finally block is completely optional.
try {
# Code that might generate an error
# ...
}
catch {
# Code to handle the error
# ...
}
finally {
# Cleanup code here
# ...
}
Terminating/non-terminating Errors Link to heading
non-terminating errors are any error that will not stop the execution of your script. Most cmdlets in PowerShell are non-terminating. They may output an error, but your script will continue to run. These kinds of errors cannot be caught with a catch block by default. The reason for this is the default ErrorAction
in your PowerShell profile, which is set to Continue
.
# To show your default error action type
$ErrorActionPreference
Let’s go back and look at our first example:
try {
# Code that might generate an error
Get-Item -Path "NonexistentFile.txt"
}
catch {
# Code to handle the error
Write-Host "An error occurred: $_"
}
If you took the time to run this code, you may have noticed that the Write-Host
cmdlet in the catch
block was never ran. Why did we get a red error message in our PowerShell console, rather than the text An error occurred: ...
? The reason is that the non-existing path isn’t a terminating error, and the default ErrorAction
is Continue
. To catch the error, you will need to change the ErrorAction
in your PowerShell console to Stop
. This can be done in multiple ways. You can add -ErrorAction Stop
to the cmdlet, like this:
try {
# Code that might generate an error
Get-Item -Path "NonexistentFile.txt" -ErrorAction Stop
}
catch {
# Code to handle the error
Write-Host "An error occurred: $_"
}
Or you can change the ErrorActionPreference
for the entire script, by adding this to the top of the script:
$ErrorActionPreference = "Stop"
Exceptions Link to heading
If you have ever worked with exceptions in C# you can skip this section. In the previous examples, we used simple catch
blocks that will catch any error. This is a good start, but we can do better. PowerShell allows you to catch individual exceptions based on the exception type, similar to how C# handles catching exceptions.
Let’s look at an example:
try {
# Attempt to open a non-existent file
$file = Get-Content -Path "NonexistentFile.txt"
}
catch [System.IO.FileNotFoundException] {
Write-Host "Caught a FileNotFoundException: $_"
}
catch {
Write-Host "Caught an exception: $_"
}
We now have two catch
blocks. If we encounter an exception of type System.IO.FileNotFoundException
, the first catch
block will catch the exception and handle it accordingly. The second catch
block will handle any other generic error.
Conclusion Link to heading
Error handling might seem daunting at first, but with the power of Try-Catch-Finally blocks at your fingertips, you’re well-equipped to handle errors gracefully and ensure the resilience of your PowerShell scripts. Remember, every error is an opportunity to refine your skills and make your scripts more robust.
Thanks for reading!
Official Microsoft Documentation for Try-Catch-Finally in PowerShell: about_try_catch_finally