Error Handling With PowerShell Try Catch Blocks

PowerShell

Windows PowerShell has a robust error handling capability with PowerShell try catch blocks. And PowerShell 7 introduced new features, making troubleshooting even easier. In this article, I will show you how to use PowerShell’s built-in error handling features to help debug your scripts when there are problems.

Understanding PowerShell Try Catch error handling

First, it helps to have a good understanding of errors within PowerShell. A common operation is to test the network connection to another system using the Test-Connect cmdlet. The example is using a computer name of fakesystem, that isn’t going to work, and only 1 ICMP ping is being sent to simplify testing (default is 4 ICMP pings).

​Test-Connection "fakesystem" -Count 1
PowerShell Test-Connection cmdlet
PowerShell Test-Connection cmdlet

Adding a try-catch block to your code

As expected the operation failed, but it would be nice to output a nicer error message then that. To “catch” the error, we use a try-catch block. By wrapping our code in this block, any error will be caught and we can then output an appropriate message or take some other action. Let’s give this a try below. You should expect to see Error in the output.

​Try {
  Test-Connection "fakesystem" -Count 1
} Catch {
  "Error"
}
Test-Connection with PowerShell Try Catch
Test-Connection with PowerShell Try Catch

Terminating vs. non-terminating PowerShell errors

Instead you see the same error message as before, ...No such host is known..., but shouldn’t we see Error? The Test-Connection cmdlet outputs something called a non-terminating error. There are two types of errors, Terminating and Non-Terminating. Terminating errors stop execution whereas non-terminating writes to the error stream but does not stop the pipeline execution. The try-catch block only catches terminating errors.

Adding the -ErrorAction parameter to a cmdlet

How do we make Test-Connection throw a terminating error then? Thankfully there is a handy parameter available to most functions called, ErrorAction. You can configure the cmdlets error handling behavior to throw a terminating error by specifying Stop as the value.

​Try {
  Test-Connection "fakesystem" -Count 1 -ErroAction 'Stop'
} Catch {
  "Error"
}
Try Catch with tidy error output
Try Catch with tidy error output

Now when you run the above code, you will get Error as the output. The output of just what we define for the error message is much more concise and opens up the door to customized error messages. Often though, instead of catching all errors equally, maybe you want to customize how each exception type is handled. try-catch can do this, but you first need to know what the exception is.

Inspect the global $Error variable

After running the above code, you can inspect the global $Error variable and as you can see below what exception type was thrown:

​$Error[0].Exception.GetType().FullName
Finding the error exception type in PowerShell
Finding the error exception type in PowerShell

Print an error message to handle a specific exception type

Now that we know the specific exception type is System.Net.NetworkInformation.PingException we can catch just this error. The code below will output Ping Exception and as you can tell we can chain multiple exception types with a default value at the end.

​Try {
  Test-Connection "fakesystem" -Count 1 -ErrorAction 'Stop'
} Catch [System.Net.NetworkInformation.PingException] {
  "Ping Exception"
} Catch {
  "Unknown Exception"
}
Writing a specific error message to the PowerShell terminal
Writing a specific error message to the PowerShell terminal

PowerShell 7 and new error handling functionality

All this is very cool and useful but how does PowerShell 7 help us here? As you’ve no doubt noticed, unless you are turning everything into terminating errors using ErrorAction 'Stop', this will quickly become difficult to manage.

Related article: Understanding the PowerShell 7 Error Variable

PowerShell 7 has a brand new error view option called ConciseView. Set the preference variable $ErrorView to 'ConciseView' or to get the same view as before set the variable to 'NormalView'. With ConciseView turned on (the default in PowerShell 7) let’s see what our output looks like now with the Test-Connection example.

​Test-Connection "fakesystem" -Count 1
PowerShell 7 concise view error
PowerShell 7 concise view error

The three ErrorView options for the $ErrorView variable

Below is a view of each of the three ErrorView options and how they display the error of the Test-Connection example.

The three ErrorView options for the $ErrorView variable
The three ErrorView options for the $ErrorView variable

The PowerShell Get-Error cmdlet

That is a whole lot easier to digest! What if you need to dive into the error to understand what’s going on though? With PowerShell 7 there is a brand new cmdlet named Get-Error. This cmdlet outputs a ton of very useful and interesting information.

If we run Get-Error with no arguments, it outputs all the information on the last error to be shown. In this case, that of our Test-Connection failure as shown below.

​Get-Error
PowerShell 7 Get-Error cmdlet
PowerShell 7 Get-Error cmdlet

Woah, that is a lot more than expected! What’s great about this is that it displays not only the basic exception but also the InnerException and a StackTrace which dives into the internals and displays a lot of useful information, especially if we don’t really know what went wrong.

How PowerShell 7 makes error handling easier

As you can tell, error handling in PowerShell is robust and can be well controlled. With the addition of a more concise view for errors in the console, and the additional added ability to easily dive into the underlying reasons for an error, PowerShell 7 has upped the game in helping you troubleshoot your functions, scripts, and modules!