about_Try_Catch_Finally

Short description

Describes how to use the try, catch, and finally blocks to handle terminating errors.

Long description

Use try, catch, and finally blocks to respond to or handle terminating errors in scripts. The Trap statement can also be used to handle terminating errors in scripts. For more information, see about_Trap.

A terminating error stops a statement from running. If PowerShell does not handle a terminating error in some way, PowerShell also stops running the function or script using the current pipeline. In other languages, such as C#, terminating errors are referred to as exceptions.

Use the try block to define a section of a script in which you want PowerShell to monitor for errors. When an error occurs within the try block, the error is first saved to the $Error automatic variable. PowerShell then searches for a catch block to handle the error. If the try statement does not have a matching catch block, PowerShell continues to search for an appropriate catch block or Trap statement in the parent scopes. After a catch block is completed or if no appropriate catch block or Trap statement is found, the finally block is run. If the error cannot be handled, the error is written to the error stream.

A catch block can include commands for tracking the error or for recovering the expected flow of the script. A catch block can specify which error types it catches. A try statement can include multiple catch blocks for different kinds of errors.

A finally block can be used to free any resources that are no longer needed by your script.

try, catch, and finally resemble the try, catch, and finally keywords used in the C# programming language.

Syntax

A try statement contains a try block, zero or more catch blocks, and zero or one finally block. A try statement must have at least one catch block or one finally block.

The following shows the try block syntax:

try {<statement list>}

The try keyword is followed by a statement list in braces. If a terminating error occurs while the statements in the statement list are being run, the script passes the error object from the try block to an appropriate catch block.

The following shows the catch block syntax:

catch [[<error type>][',' <error type>]*] {<statement list>}

Error types appear in brackets. The outermost brackets indicate the element is optional.

The catch keyword is followed by an optional list of error type specifications and a statement list. If a terminating error occurs in the try block, PowerShell searches for an appropriate catch block. If one is found, the statements in the catch block are executed.

The catch block can specify one or more error types. An error type is a Microsoft .NET Framework exception or an exception that is derived from a .NET Framework exception. A catch block handles errors of the specified .NET Framework exception class or of any class that derives from the specified class.

If a catch block specifies an error type, that catch block handles that type of error. If a catch block does not specify an error type, that catch block handles any error encountered in the try block. A try statement can include multiple catch blocks for the different specified error types.

The following shows the finally block syntax:

finally {<statement list>}

The finally keyword is followed by a statement list that runs every time the script is run, even if the try statement ran without error or an error was caught in a catch statement.

Note that pressing CTRL+C stops the pipeline. Objects that are sent to the pipeline will not be displayed as output. Therefore, if you include a statement to be displayed, such as "Finally block has run", it will not be displayed after you press CTRL+C, even if the finally block ran.

Catching errors

The following sample script shows a try block with a catch block:

try { NonsenseString }
catch { "An error occurred." }

The catch keyword must immediately follow the try block or another catch block.

PowerShell does not recognize "NonsenseString" as a cmdlet or other item. Running this script returns the following result:

An error occurred.

When the script encounters "NonsenseString", it causes a terminating error. The catch block handles the error by running the statement list inside the block.

Using multiple catch statements

A try statement can have any number of catch blocks. For example, the following script has a try block that downloads MyDoc.doc, and it contains two catch blocks:

try {
   $wc = new-object System.Net.WebClient
   $wc.DownloadFile("http://www.contoso.com/MyDoc.doc","c:\temp\MyDoc.doc")
}
catch [System.Net.WebException],[System.IO.IOException] {
    "Unable to download MyDoc.doc from http://www.contoso.com."
}
catch {
    "An error occurred that could not be resolved."
}

The first catch block handles errors of the System.Net.WebException and System.IO.IOException types. The second catch block does not specify an error type. The second catch block handles any other terminating errors that occur.

PowerShell matches error types by inheritance. A catch block handles errors of the specified .NET Framework exception class or of any class that derives from the specified class. The following example contains a catch block that catches a "Command Not Found" error:

catch [System.Management.Automation.CommandNotFoundException]
{"Inherited Exception" }

The specified error type, CommandNotFoundException, inherits from the System.SystemException type. The following example also catches a Command Not Found error:

catch [System.SystemException] {"Base Exception" }

This catch block handles the "Command Not Found" error and other errors that inherit from the SystemException type.

If you specify an error class and one of its derived classes, place the catch block for the derived class before the catch block for the general class.

Note

PowerShell wraps all exceptions in a RuntimeException type. Therefore, specifying the error type System.Management.Automation.RuntimeException behaves the same as an unqualified catch block.

Using Traps in a Try Catch

When a terminating error occurs in a try block with a Trap defined within the try block, even if there is a matching catch block, the Trap statement takes control.

If a Trap exists at a higher block than the try, and there is no matching catch block within the current scope, the Trap will take control, even if any parent scope has a matching catch block.

Accessing exception information

Within a catch block, the current error can be accessed using $_, which is also known as $PSItem. The object is of type ErrorRecord.

try { NonsenseString }
catch {
  Write-Host "An error occurred:"
  Write-Host $_
}

Running this script returns the following result:

An Error occurred:
The term 'NonsenseString' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.

There are additional properties that can be accessed, such as ScriptStackTrace, Exception, and ErrorDetails. For example, if we change the script to the following:

try { NonsenseString }
catch {
  Write-Host "An error occurred:"
  Write-Host $_.ScriptStackTrace
}

The result will be similar to:

An Error occurred:
at <ScriptBlock>, <No file>: line 2

Freeing resources using finally

To free resources used by a script, add a finally block after the try and catch blocks. The finally block statements run regardless of whether the try block encounters a terminating error. PowerShell runs the finally block before the script terminates or before the current block goes out of scope.

A finally block runs even if you use CTRL+C to stop the script. A finally block also runs if an Exit keyword stops the script from within a catch block.

See also