Error handling in PowerShell

Before we go ahead and talk about how to handle errors or avoid them while writing scripts in PowerShell, let's speak about a few of the inherent features of advanced functions that can help end users. These are Write-Verbose, Write-Error, Write-Warning, and –Whatif. These are not typical error handling ways in PowerShell, but by using these in advanced functions, you can provide more ways to avoid errors in scripts.

Write-Verbose allows you to define more information for end users when they run the script/function/cmdlet with the –Verbose option. The same goes for the Write-Error and Write-Warning options. Defining –Whatif would allow end users to know what exactly the script will do if it is run normally. The following is a sample script showing all of these:

Error handling in PowerShell

–WhatIf will only show the purpose of the script. If more than two VMnames are provided, then there will be an error message shown but not providing any VM name will result in an error. The following is a screenshot showing all of these use cases in the script:

Error handling in PowerShell

Now that we have covered a few of the remaining ways to provide more information for the end users, let's dive into error handling in PowerShell. Actually, PowerShell provides a powerful in-built capability for controlling the behavior of the function/script if any error is encountered.

$ErrorActionPreference is the variable that controls the behavior of the script when a nonterminating error (an error that does not stop the script) is encountered.

The values that can be provided to this variable are as follows:

  • Stop: This displays the error and stops the execution of the script.
  • Inquire: This displays the error message and asks the user whether the execution will continue or not.
  • Continue: This is the default behavior. With this option, PowerShell displays the error and continues with the execution.
  • Suspend: With this option, PowerShell automatically suspends a workflow job and allows further investigation. Once the investigation is done, the execution can continue.
  • SilentlyContinue: With this option, there is no effect of an error on the execution. The error message is not shown and the execution continues.

Providing the $ErrorAction value per command will override the overall $ErrorActionPreference value. Here are some examples:

Error handling in PowerShell

Note the difference between SilentlyContinue and Continue. While SilentlyContinue will not show any error, Continue will show the error and continue.

Error handling in PowerShell
Error handling in PowerShell
Error handling in PowerShell

Next, we can see the $ErrorVariable parameter. With this parameter, we can save the error value in a variable and later use this variable to get the error message:

Error handling in PowerShell

If you want to debug the script, PowerShell provides an in-built way to do this. Just use the Set-PSDebug cmdlet. This particular cmdlet will allow you to debug the script and set the level at which you want to debug. Setting the trace level to 1 will provide generic information, level 2 will provide more information, and setting it to 0 will bring it back to normal. The following table will show you the values and what each does:

Error handling in PowerShell

If you want to step through the script, then you can do it using the –Step parameter, as shown in the following example:

Error handling in PowerShell

In this case, in each and every step, you need to provide an input so that debug can step through the entire script.

The next portion talks about two more ways of handling errors in PowerShell scripts: the Trap and try,catch, and finally blocks. Both of them are used to handle terminating errors.

A terminating error in PowerShell is one that stops Shell from continuing further execution. Let's discuss them one by one.

Trap:

The trap keyword will allow us to specify a list of commands to be run if a terminating error occurs. The trap statements handle the errors and allow the execution to continue without stopping.

The syntax for the keyword is as follows:

trap [[<error type>]] {<statement list>}

Note that, in the place of <error type>, we can provide the particular error type that we are expecting (if we already know the error type). This is optional and can be omitted. We can also use continue or break in the trap statement list so that it can be decided whether the execution will continue or break once the error occurs. Here are two examples of this:

Error handling in PowerShell
Error handling in PowerShell

Try, Catch, and Finally:

We need to use the try block to monitor any error that may occur in PowerShell. If any error occurs in the try block, then first, the error is saved in the $Error automatic variable. PowerShell then searches for the Catch block to handle the error. If there is no matching Catch block for the try block, then PowerShell continues to search for a matching Catch block. Once a Catch block is completed or if a matching Catch block is not found or a trap statement is found, then the Finally block is run. If the error cannot be handled, then it is written to the error stream.

A typical try, catch, finally block syntax is shown here:

          try
          {
<Statement Block>
          }
          catch [[<error type>][',' <error type>]*] {<statement list>}
          }
          catch
          {
<Statement Block>
          }
Finally { <Statement list>}

The following is an example of such a function using all the three blocks:

Error handling in PowerShell

For more details on the preceding topics, check out https://technet.microsoft.com/en-us/library/hh847742.aspx and https://technet.microsoft.com/en-us/library/hh847793.aspx.