PowerShell How-To

Understanding the Try/Catch Block in PowerShell

Try and catch blocks are designed to catch errors in your code, no matter the situation.

Error handling is important when creating PowerShell scripts. A script that runs correctly once may not run correctly every time. There always seems to be some kind of problem that crops up when you least expect it. This is why error handling should be implemented in every piece of PowerShell code you create.

A staple of error handling in PowerShell is the try and catch blocks. The try and catch blocks. more often just called a try/catch block. is a construct that implements a "net" of sorts to catch errors in your code. To be more specific, when an exception is thrown anywhere inside of a try block, there's a catch block that's there to catch the thrown exception and do something with it. In PowerShell, an exception is a terminating error.

There are many uses of a try/catch block, but a common one is being placed inside of a function to catch any terminating errors that may come up inside of the function. Perhaps I have a function that I have added a try/catch block to that looks like this:

Function Do-Something {
[CmdletBinding()]
param()

            try {
## Ensure the thing exists. If not, this function will not continue
if (-not (Test-Path –Path 'C:\FileThatDoesNotExist.txt')) {
Write-Host 'The file does not exist'
}
Write-Host 'The file does exist'
} catch {

            }
}

Above I'm testing if something exists. In this case, it's a file. If not, the function needs to stop. At this point though when I run this I find that it's running both cases.

Figure 1.

The reason is that I just use an if statement. There's no else statement to accompany it. Rather than putting in an if/then/else statement, I need another way. This is where the throw command comes in.

The throw command is how exceptions are thrown to the catch block. Once an exception is thrown to the catch block, PowerShell will skip over everything else in the try block. Throw commands accept messages which typically indicate the error that occurred. In our example, I would like to let the user know that the file did not exist by throwing an exception to the catch blog. Our command might now look something like this:

Function Do-Something {
[CmdletBinding()]
param()

            try {
## Ensure the thing exists. If not, this function will not continue
if (-not (Test-Path –Path 'C:\FileThatDoesNotExist.txt')) {
throw 'The file does not exist'
}
Write-Host 'The file does exist'
} catch {

            }
}

I run it now and did not get a second message, but I didn't get anything at all!

Figure 2.

The reason was that the throw command did its job and skipped over the other Write-Host reference, but I had nothing in the catch block to something with the exception.

When an exception enters the catch block, it's always represented as the familiar pipeline variable $_. Here, I'll simply make a reference to that variable which will get output to the console.

Function Do-Something {
[CmdletBinding()]
param()

            try {
## Ensure the thing exists. If not, this function will not continue
if (-not (Test-Path –Path 'C:\FileThatDoesNotExist.txt')) {
throw 'The file does not exist'
}
Write-Host 'The file does exist'
} catch {
$_
}
}

[Click on image for larger view.] Figure 3.

You'll see the message that was thrown along with some familiar-looking error details although not in red. This is an error record and is commonly shown when errors occur in various PowerShell commands. Do you need to make this in the official red? No problem. Let's treat this exception as an actual error by sending it to the error stream with Write-Error.

Function Do-Something {
[CmdletBinding()]
param()

            try {
## Ensure the thing exists. If not, this function will not continue
if (-not (Test-Path –Path 'C:\FileThatDoesNotExist.txt')) {
throw 'The file does not exist'
}
Write-Host 'The file does exist'
} catch {
Write-Error $_
}
}

[Click on image for larger view.] Figure 4.

That's better. You can do anything you want with this error record object like parsing the message in different ways, displaying a warning instead of an error, etc.

A try/catch block is an excellent way to handle both errors that you anticipate by manually throwing the exception in code as well as exceptions that are thrown by other cmdlets. The catch block will catch any exception thrown inside of the try block regardless of where it originated from.

About the Author

Adam Bertram is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at adamtheautomator.com or on Twitter at @adbertram.

comments powered by Disqus

SharePoint Watch

Sign up for our newsletter.

I agree to this site's Privacy Policy.