A Look at Try/Catch in PowerShell

My article here wraps up PowerShell Blogging Week (#PSBlogWeek), which has been a series of articles on Windows PowerShell Advanced Functions. We hope that you have enjoyed this series and hope you will supply us with more ideas so we can continue to provide fun and useful material for you!

When working with errors and trying to get a handle on them, you need to use what is available to not only catch them, but also to determine what the next course of action is after you have caught them. In this article, I am focusing solely on Try/Catch (along with Finally) and how you can use these to perform some essential error handing in your scripts.

Let’s break down each of these statements and what they accomplish.

Try

Try is where you are going to place your code block in that you want to watch for errors that will be handled later on in the script. Know that wherever the error occurs, it will immediately stop at that point and move onto the Catch keyword (assuming that the error is a terminating error). During this you need to ensure that you either have $ErrorActionPreference=’Stop’ so every error that occurs is considered a terminating error (useful when working with outside commands that do not throw terminating errors by default) or you can make use of –ErrorAction ‘Stop’ in a cmdlet to force the cmdlet to throw a terminating error.

Note: Did you know that using the Throw keyword says that the error being thrown is a terminating error? Try it in a Try/Catch and see what happens!

Here is an action of what be in a Try statement:

Try {
    Write-Verbose "[TRY] Checking for OS" -Verbose
    $OS = Get-WmiObject -ComputerName RemoteServer -Class Win32_OperatingSystem -ErrorAction Stop
    Write-Verbose "[TRY] No issues found" -Verbose
}

Assuming that I can connect to this remote system, I should see the Verbose output afterwards, otherwise based on the ErrorAction of Stop, it will send the execution down to the Catch statement.

Catch

Here is where the execution of code continues after an error occurs within the Try statement. One of the neat things about using Catch is that you can have multiple Catch statements based on the error type that you want to handle. If you want to take a different action on an Access Denied error, you can specify the System.UnauthorizedAccessException type and anytime the error record relates to an unauthorized access exception, it will be handled in that statement while all other errors will be handles by the Catch statement with no exception type defined. Think of this one as the ‘catch all’ Catch block. Here is an example of such a Catch statement.

Catch [System.UnauthorizedAccessException] {
    Write-Warning "[CATCH] You do not have the proper access to this system!"
    BREAK
}
Catch [System.Runtime.InteropServices.COMException] {
    Write-Warning "[CATCH] Communications Exception occurred!"
    BREAK
}
Catch {
    Write-Warning "[CATCH] Errors found during attempt:`n$_"
    BREAK
}

Finally

This keyword performs an action regardless of what happens in the Try/Catch statements. This allows you to perform a sort of cleanup of resources or anything else that you may want to do. Even if we specify BREAK in our Catch block, this will still run any code that happens to be in the Finally block. In fact, even adding Exit to my Catch block will not prevent anything in the Finally block from running before the session is closed.

Finally {
    Write-Verbose "[FINALLY] Performing cleanup actions." -Verbose
}
Write-Verbose "Doing something outside of Try/Catch/Finally" -Verbose

Note that I added some verbose output to run outside of the Finally block. If something throws a terminating error, you will see the Verbose output in the Finally block, but nothing beyond that.

Putting it all together

Putting this all together, we can see how these all come together to work just like we want them to. First let’s see a good attempt with our code:

clip_image002

Now let’s try this with a known issue happening:

clip_image004

Notice that we did not see the verbose output that exists outside of the Try/Catch/Finally blocks. You can also notice that it caught the System.Runtime.InteropServices.ComException exception rather than the ‘catch all’ block. Had I run into an issue where I was getting access denied, the System.UnauthorizedAccessException would have caught the error, otherwise my last Catch block will get the error.

With that, you can see how to use Try/Catch/Finally to control the flow of your code in the event of errors during execution. Of course, this wasn’t an exhaustive look at error handling but is still helpful to get your going!

Hungry for more information about Try/Catch and error handling? Check out the following links for more information about this topic:

#PSBlogWeek Articles:

This entry was posted in powershell and tagged , , , , . Bookmark the permalink.

11 Responses to A Look at Try/Catch in PowerShell

  1. misdemeanor says:

    Excellent review, this is the most complete tutorial I’ve seen for the try…catch construct. Very helpful, thank you very much.

  2. Tony R Auby says:

    I read in another PS error-handling post that even if you use -ErrorAction stop, if the error is non-terminating from the original command that issued the exception, then you cannot ‘catch’ specific exceptions in the catch blocks. Not sure what the behavior will be. Maybe only the catch-all block will catch.

  3. Pingback: PowerShell Blogging Week: Supporting WhatIf and Confirm | The Lonely Administrator

  4. Pingback: #PSBlogWeek - Dynamic Parameters and Parameter Validation - Adam, the Automator

  5. Pingback: Free eBook on PowerShell Advanced Functions | Mike F Robbins

  6. Pingback: Quick Hits: Finding Exception Types with PowerShell | Learn Powershell | Achieve More

  7. Pingback: SAPIEN Technologies » Blog Archive » Advanced Help for Advanced Functions – #PSBlogWeek

  8. Pingback: PowerShell Advanced Functions: Can we build them better? With parameter validation, yes we can! | Mike F Robbins

  9. The first time I saw a multiple catch statement was in the MSFT_xADUser module, that blew my mind! I was like “Wait, you can do that?” Certainly helps with drilling down to a specific error.

  10. Pingback: #PSBlogWeek 6 – A Look at Try / Catch in PowerShell by Boe Prox |

Leave a comment