MSDN Documentation

PowerShell Error Handling

Effective error handling is crucial for writing robust and reliable PowerShell scripts. PowerShell provides several mechanisms to manage and respond to errors, ensuring your scripts behave predictably even when encountering unexpected situations.

Types of Errors in PowerShell

PowerShell categorizes errors into two main types:

  • Terminating Errors: These errors stop the script's execution by default. Examples include syntax errors, attempting to access a non-existent file, or calling a cmdlet that is not found.
  • Non-Terminating Errors: These errors do not stop script execution by default. The script continues to run, but an error record is generated. Examples include a cmdlet failing to process a single item in a collection, but being able to continue with the rest.

Error Handling Cmdlets

PowerShell provides specific cmdlets to control error flow and handle errors gracefully:

The try-catch-finally Block

This is the most common and structured way to handle terminating errors. The try block contains the code that might cause an error, the catch block executes if a terminating error occurs in the try block, and the finally block executes regardless of whether an error occurred.

Example: Basic try-catch


try {
    # Code that might cause a terminating error
    Get-ChildItem -Path "C:\NonExistentFolder" -ErrorAction Stop
    Write-Host "This line will not be reached if an error occurs."
}
catch {
    # This block executes if a terminating error occurs in the try block
    Write-Host "An error occurred!" -ForegroundColor Red
    Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Yellow
    # You can also access the full error record via $_
    # $_ | Format-List *
}
finally {
    # This block always executes
    Write-Host "Execution finished (try-catch-finally)."
}
                    

The catch block can also be more specific by catching particular error types:

Example: Catching Specific Error Types


try {
    # Simulate an error that results in a specific exception type
    "Hello" | Integer
}
catch [System.Management.Automation.MethodInvocationException] {
    Write-Host "Caught a MethodInvocationException!" -ForegroundColor Cyan
}
catch {
    Write-Host "Caught a general error." -ForegroundColor Gray
}
                    

The trap Statement

The trap statement provides an alternative way to handle terminating errors. When a terminating error occurs within a script or function that has a trap statement, control is transferred to the trap handler.

Example: Using trap


trap {
    Write-Host "A terminating error was trapped!" -ForegroundColor Magenta
    Write-Host "Error Message: $($_.Exception.Message)"
    # 'continue' will allow the script to continue after the trap handler.
    # 'break' will exit the script.
    continue
}

Write-Host "Starting script..."
Get-ChildItem -Path "C:\AnotherNonExistentFolder" -ErrorAction Stop
Write-Host "This line might or might not be reached depending on trap action."
                    

Note: trap statements are often scoped to the block or function they are defined in. They are generally considered less flexible than try-catch for complex error handling scenarios.

ErrorAction Parameter

Most PowerShell cmdlets accept the -ErrorAction parameter, which controls how the cmdlet responds to terminating and non-terminating errors. Common values include:

  • Continue (default for non-terminating errors): Writes an error record and continues execution.
  • Stop: Turns a non-terminating error into a terminating error, stopping the script's execution. This is useful when you want try-catch to handle a specific error.
  • SilentlyContinue: Suppresses any error messages and continues execution. Use with caution.
  • Ignore: Suppresses error messages but still generates an error record.

Example: Using -ErrorAction


# Non-terminating error with default behavior (Continue)
Get-ChildItem -Path "C:\InvalidPathDoesNotExist"

# Turning a non-terminating error into a terminating one
try {
    Get-ChildItem -Path "C:\InvalidPathDoesNotExist" -ErrorAction Stop
}
catch {
    Write-Host "Handled the error that was forced to Stop." -ForegroundColor Yellow
}

# Silently continuing
Get-ChildItem -Path "C:\InvalidPathDoesNotExist" -ErrorAction SilentlyContinue
Write-Host "Script continued after silent error."
                    

The Automatic Variable $?

The automatic variable $? returns a boolean value indicating whether the last operation was successful. $true if the last command completed successfully, $false otherwise.

Example: Checking $?


Get-Process notepad -ErrorAction SilentlyContinue
if ($?) {
    Write-Host "Notepad process is running."
} else {
    Write-Host "Notepad process is not running."
}
                    

The Automatic Variable $$

The automatic variable $$ contains the last error record generated by the last command. This can be useful within catch blocks or when inspecting errors programmatically.

Example: Accessing the Last Error


try {
    Get-ChildItem -Path "C:\AnotherNonExistentFolder" -ErrorAction Stop
}
catch {
    Write-Host "Error Type: $($_.Exception.GetType().FullName)"
    Write-Host "Error Message: $($_.Exception.Message)"
    Write-Host "FullyQualifiedErrorId: $($_.FullyQualifiedErrorId)"
}
                    

Best Practices for Error Handling

  • Use try-catch-finally for structured error handling.
  • Use -ErrorAction Stop when you want a specific error to be caught by a try-catch block.
  • Be specific in your catch blocks when possible.
  • Log errors appropriately, especially in production scripts.
  • Avoid -ErrorAction SilentlyContinue unless you are absolutely sure you want to ignore the error and its side effects.
  • Provide informative error messages to the user.

By mastering these error handling techniques, you can significantly improve the reliability and maintainability of your PowerShell scripts.