PowerShell Error Handling

*If you're just joining us, this post is part of a series on Getting Started with PowerShell. If you'd like to catch up (or skip ahead), click on the appropriate post below.

Getting Started with PowerShell
Windows PowerShell, PowerShell Core and PowerShell: Huh?
Installing PowerShell and Visual Studio Code
Running PowerShell Commands and Getting Help
Working with the PowerShell Pipeline
Writing your First PowerShell Script
Understanding Loops in PowerShell
Using PowerShell Modules
Connecting to Azure

We all would like to think our scripts never run into an error. And that we only write the best of the best. We'd be wrong.

Regardless of how much time and effort you put into writing a PowerShell script to run perfectly, an error will creep in with you least expecting it.

To ensure we set up a net to catch all of the errors that are bound to happen, it's important to understand error handling. Error handling is a concept in all programming languages that outlines steps, procedures and code that's written to intelligently capture errors and do something about them. PowerShell is no different.

In this article in our Getting Started with PowerShell series, you're going to learn:

  • when to use error handling techniques

  • where errors might pop up

  • how to prevent them from derailing your blood, sweat and tears PowerShell script

Let's get going!

Error Handling: Expect the Unexpected

In a nutshell, error handling is attempting to code for the unexpected. When you begin writing more advanced scripts, you'll find many different ways the code fails. Regardless of how many times you test a script, unless it's run exactly the same way in the exact same environment, chances are it might fail.

Let's suppose you, the reader were casually following along in the previous post on creating your first PowerShell script <link here>. After you followed each step provided, you were able understand the code snippet we covered earlier below.

The code snippet below finds the notepad process. If found, it then stops the process. Simple enough, right? Not quite.

$process = Get-Process -Name notepad
if ($process) {
    $process | Stop-Process
}

The code above works fine if notepad is open but try it when it's not. You'll be presented with that lovely red text.

Error for command not finding Notepad

That was unexpected.

Understanding Terminating vs. Non-Terminating Errors

The error you saw above in the ugly red text was one of two types - terminating or non-terminating. Which one it was, you can't tell by just viewing the error message. Let's find out.

A terminating error is one that's been labeled as bad enough to completely stop code execution. When you run a script and the script encounters a terminating error, the entire script stops. The error terminates execution. You'll see one error message and the entire script halts.

Some errors aren't quite as serious. These errors are called non-terminating errors. Non-terminating errors do not halt code execution. Instead, they spit out the error and the script continues. These errors aren't considered important enough to stop everything.

Take the above example of attempting to find the notepad process using Get-Process. That command returned an error but what kind? To find out, you need to use a common parameter on all PowerShell commands called ErrorAction. This parameter is available on all commands in PowerShell and controls what happens when a non-terminating error is returned.

To demonstrate, ensure notepad is closed and running the following command.

Get-Process -Name notepad -ErrorAction Ignore

Notice that nothing happens. We've confirmed that when the notepad process does not exist, Get-Process returns a non-terminating error. If this code were in a script, the script would continue to run.

Let's say you disagree with PowerShell and think this command should return a terminating error. The case when the notepad process doesn't exist should stop a script. In that case, use Stop for the ErrorAction.

Get-Process -Name notepad -ErrorAction Stop

When you run a command using the Stop value, PowerShell treats any errors returned as terminating and acts accordingly.

You can control non-terminating and terminating errors globally using the $ErrorActionPreference variable.

Catching Unexpected Errors

A script's goal is not to return any errors - it's to not return unexpected errors. But how are you supposed to know when an error will happen? You build a net or, more specifically, you try to catch an error.

To build an "error net", you need to understand try/catch blocks. When a terminating error is returned from a command that's known as throwing. PowerShell throws terminating errors. Without any other code around, PowerShell throws that error which stops code execution.

The key to error handling is catching errors as they happen and then doing something about that in code. Let's take our Get-Process scenario for example.

Previously, when you ran Get-Process -Name notepad -ErrorAction Stop, a terminating error was thrown and you saw the error message in the console. If that line were in a script, what kind of action would you like to perform if an error was thrown?

If you run the below code, it won't work. PowerShell will die at line one if notepad isn't running.

$process = Get-Process -Name notepad
if ($process) {
    $process | Stop-Process
}

How would you ensure notepad is stopped? By introducing a try/catch block. A try/catch block is actually two blocks indicated by the opening and closing curly braces. To implement a try/catch block, add all of the code that is capable of throwing an error inside of the try block. Then, add the code to run if the error is thrown inside the catch block.

You can see below a well-handled script. If the notepad process is started, no error will be thrown and the script will stop the process. But if the process is not started, the script will throw an error, end up in the catch block and return a nice message.

try {
    $process = Get-Process -Name notepad -ErrorAction Stop
    $process | Stop-Process
} catch {
    Write-Host "The notepad process was not started."
}

The try/catch block is your friend when handling errors.

Conclusion

Introducing error handling ups your PowerShell game. If you're properly implementing error handling techniques, you've graduated from a beginner to intermediate-level scripter. Error handling is a critical skill to learn if you intend to write scripts of any complexity.

Remember to wrap a try block around code that may return a terminating error and be sure to handle that scenario in the catch block.

 
Adam Bertram

About the Author

Hi, I'm Adam. I'm a 20+ year veteran of IT and experienced online business professional. I'm an entrepreneur, IT influencer, Microsoft MVP, blogger, trainer, author and content marketing writer for multiple technology companies.

Follow me on my blog, Twitter, LinkedIn

 
Previous
Previous

AZ-900: Compute

Next
Next

Azure AD Connect - Step by Step