PowerShell catching typed exceptions

16,651

When you set ErrorAction to Stop, non-terminating errors are wrapped and thrown as type System.Management.Automation.ActionPreferenceStopException, this is the type you want to catch.

try 
{
    Get-Process -Id 123123 -ErrorAction Stop
} 
catch [System.Management.Automation.ActionPreferenceStopException]
{
    ... do something ...
}
Share:
16,651

Related videos on Youtube

David Thomas
Author by

David Thomas

Updated on June 04, 2022

Comments

  • David Thomas
    David Thomas almost 2 years

    I'm having an issue with PowerShell where it will not catch an exception even when the exception is explicitly mentioned in the catch command.

    In this case, I'm trying to determine if a ProcessID is still running, and if not then it will take some actions.

    The sample code block that I am struggling with is:

        try {
          Get-Process -Id 123123 -ErrorAction 'Stop'
        } 
        catch [Microsoft.PowerShell.Commands.ProcessCommandException] {
          "Caught by Exception Type: Process is missing"
        }
        catch {
        if ($_.Exception.getType().FullName -eq "Microsoft.PowerShell.Commands.ProcessCommandException") {
          "Caught by Catch All: Process is missing"
          }
        }
    

    When this code block is executed the output is:

    Caught by Catch All: Process is missing
    

    You would expect the first catch condition to trigger as it names the exception being thrown correctly, but it doesn't trigger.

    To make things worse, when the second catch command runs (which catches anything) it queries the name of the exception type and checks if it is "Microsoft.PowerShell.Commands.ProcessCommandException" (which it is) and then takes appropriate steps.

    I know I can work around this, but I feel I'm missing a fundamental way about how PowerShell handles Exceptions.

    Can anyone shed light on this for me?

  • David Thomas
    David Thomas over 12 years
    Thank you very much, that was it. I was sure it was being wrapped in something but for the life of me I couldn't workout what the wrapping exception type was. At least once caught that way I can query on the .getType().FullName to validate the error type. Interestingly, it doesn't matter if -ErrorAction 'Stop' is used or $ErrorActionPreference = 'Stop' the result is the same.
  • Shay Levy
    Shay Levy over 12 years
    Yes, and I prefer to change it on the cmdlet level so I don't need to revert the global value each time I change its value..
  • Admin
    Admin over 11 years
    Hi, is there a explanation of how we get from the generalized object type 'Microsoft.PowerShell.Commands.ProcessCommandException' to 'System.Management.Automation.ActionPreferenceStopException' ? I'm trying to catch a exception for another class or error and get stuck in the same place as @david-thomas did.
  • Shay Levy
    Shay Levy over 11 years
    When the Stop value is specified, PowerShell captures the error and re-throw an ActionPreferenceStopException exception.
  • Justin Helgerson
    Justin Helgerson over 7 years
    @ShayLevy If you would like your script to stop execution when an error occurs is there any way to catch typed exceptions? We often set the ErrorActionPreference variable to have our scripts stop executing. How could I inspect the type of exception in that case?
  • jpmc26
    jpmc26 about 7 years
    @ShayLevy The idea that you wouldn't want to globally set it is markedly counter-intuitive to me. Wouldn't you typically want a script to stop before it spews out a crap ton of other errors and obfuscates the real one or does some kind of damage because the system is not in the expected state?
  • TurtleZero
    TurtleZero over 4 years
    7 years later: it looks like powershell doesn't wrap these exceptions anymore, and the real exception type can be captured..
  • Groostav
    Groostav over 3 years
    @TurtleZero I'm struggling with this as well. Try { kill 1234567 } catch { Write-Host "Blam!" } doesnt write 'blam', it writes the exception from kill. playing around with this, it seems that Stop-Process is writing directly to the error stream, not throwing an exception. You can use $(kill ... 2>&1). and it will give you the error text. See gist.github.com/Groostav/15ed0b2bad3d8169901ff19d08cd7c4b
  • Benjamin Zach
    Benjamin Zach over 2 years
    Could you please provide a bit more explanation about how your solution solves the issue.