Using Specific Error Handlers

by Jan 17, 2013

If you want error handler to handle specific error types, you can add the error type after the keyword trap or catch.

However, this will only work with so-called "terminating" errors. Any error that is handled by PowerShell internally (non-terminating errors) is wrapped into a specific error record and won't trigger the specific error handler.

Here is an example illustrating the dilemma:

$OldValue  = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
trap [System.Management.Automation.ItemNotFoundException]
{
  "Element not found: $_"
  continue
}

trap [System.DivideByZeroException]
{
  'Divided by zero'
  continue
}

trap [Microsoft.PowerShell.Commands.ProcessCommandException]
{
  'No such process running.'
  continue
}

trap [System.Management.Automation.RemoteException]
{
  "Console command did not succeed: $_"
  continue
}

trap
{
  "Other error occured: $_"
  continue
}

Get-ChildItem -Path c:\notpresent
1/$null
Get-Process -Name notpresent
net.exe user notpresent 2>&1

$ErrorActionPreference = $OldValue 

All four error conditions are handled by the generic trap. The specific traps are always ignored.

To make specific traps work with non-terminating errors, use a simple trick: inside a surrounding trap, re-throw the error with the underlying true error type (which can be found in the property Exception)

$OldValue  = $ErrorActionPreference
$ErrorActionPreference = 'Stop'

trap {
    trap [System.Management.Automation.ItemNotFoundException]
    {
      "Element not found: $_"
      continue
    }

    trap [System.DivideByZeroException]
    {
      'Divided by zero'
      continue
    }

    trap [Microsoft.PowerShell.Commands.ProcessCommandException]
    {
      'No such process running.'
      continue
    }

    trap [System.Management.Automation.RemoteException]
    {
      "Console command did not succeed: $_"
      continue
    }

    trap
    {
      "Other error occured: $_"
      continue
    }
    
    Throw $_.Exception
    continue
}

Get-ChildItem -Path c:\notpresent
1/$null
Get-Process -Name notpresent
net.exe user notpresent 2>&1

$ErrorActionPreference = $OldValue 

This time, all four error conditions are handled by their specific trap handlers:

Element not found: Cannot find path 'C:\notpresent' because it does not exist.
Divided by zero
No such process running.
Console command did not succeed: The user name could not be found.

Twitter This Tip! ReTweet this Tip!