Windows PowerShell is a very powerful and extremely useful tool in today’s IT. But when it comes to complex PowerShell scripts to automate tasks to make your job a little easier, handling errors properly will go a long way. Error handling shouldn’t just be limited to big and complex scripts, short scripts benefit a lot also if unexpected events are handled properly so things don’t go south.
There are two types of errors you should worry about in PowerShell — Terminating and Non-terminating errors. Terminating errors are serious errors during execution that brings the script to a complete stop. Some examples of this are non-existent cmdlets, syntax errors or other fatal errors. Non-terminating errors, on the other hand, are not so serious errors that allow execution to continue despite failures. Examples of this are file not found errors or permission issues. Non-terminating errors cannot be caught by default but you can treat them as terminating errors to catch and do something about them. You can also catch specific exceptions in which case you would like to perform specific actions, but you will have to know the name of the exceptions to catch them individually (no examples are provided because these are not common).
Try, Catch and Finally Blocks
The Try
block defines a section of a script to be monitored for errors. That means, if an error occurs within the Try
block, it is first saved to the $Error
automatic variable. PowerShell will then search for a Catch
block that handles the error properly. If a matching Catch
block is not found, PowerShell will continue to search for it in the parent scope.
After a Catch
block completes or if no matching Catch
block or Trap statement is found, it continues to the Finally
block (if used). Use the Finally
block to free resources used by a script after the Try
and Catch
blocks. The Finally
block runs whether the script inside the Try
block fails or not. It also runs if CTRL+C
is used to stop the script or if an Exit
keyword stops the script from within a Catch
block.
Examples
Catching a Non-Terminating Error
$strUsers = Get-Content "C:\UserList.txt"
Code language: PowerShell (powershell)
In this example, we are attempting to read a file which may or may not exist. If the file does not exist, PowerShell will still continue the execution of the script but without values in the $strUsers
variable, it may fail later. So to force PowerShell to treat this as a Terminating error, you need to tell it using the ErrorAction
parameter. By specifying -ErrorAction Stop
, you ensure that all errors that are thrown by the cmdlet are caught.
$strUsers = Get-Content "C:\UserList.txt" -ErrorAction Stop
Code language: PowerShell (powershell)
Catching a Terminating Error
Continuing from the previous example, we are attempting to read a file which may or may not exist, this is how we would structure the Try
and Catch
blocks. We put the attempt to read the file inside the Try
block and in case it fails we send an email message notifying someone that it failed from the Catch
block which then terminates the script.
Try
{
$strUsers = Get-Content "C:\UserList.txt" -ErrorAction Stop
}
Catch
{
Send-MailMessage -From from@acme.com -To to@acme.com -Subject "File Read Failed!" -SmtpServer mail.acme.com
Break
}
Code language: PowerShell (powershell)
Using a Finally Block
You can also add a Finally
block after the Catch
block to execute something that needs to run regardless of what happens inside the Try
block. So here we get the current date and time stamp and output that to a log file so we can keep track of all the file read attempts.
Try
{
$strUsers = Get-Content "C:\UserList.txt" -ErrorAction Stop
}
Catch
{
Send-MailMessage -From from@acme.com -To to@acme.com -Subject "File Read Failed!" -SmtpServer mail.acme.com
Break
}
Finally
{
$execTime = Get-Date "File read attempt at $execTime" | Out-File c:\logs\userlist.log -append
}
Code language: PowerShell (powershell)