Home > database >  Exception type details not matching in PowerShell try catch
Exception type details not matching in PowerShell try catch

Time:11-09

I am trying to find out a way to frame try catch block with various possible exception types. I got some clues from other questions to check $Error[0].Exception.GetType().FullName.

However, I am still not able to figure-out where to get the Exception class type that you have to put in front of catch keyword.

For example, when I try:

try { 1/0 } catch { $Error[0].Exception.GetType().FullName }

I get:

System.Management.Automation.RuntimeException

However, when I run below:

try { 1/0 } catch [DivideByZeroException]{ "DivideByZeroException" } catch { $Error[0].Exception.GetType().FullName }

I get:

DivideByZeroException

Where is [DivideByZeroException] found in $Error[0] in above case?

Since I can't find it anywhere in the properties of $Error[0]:

PS C:\Temp> $Error[0] | Select *


PSMessageDetails      : 
Exception             : System.Management.Automation.RuntimeException: Attempted to divide by zero. 
                        ---> System.DivideByZeroException: Attempted to divide by zero.
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(
                        FunctionContext funcContext, Exception exception)
                           at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(Int
                        erpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction
                        .Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction
                        .Run(InterpretedFrame frame)
TargetObject          : 
CategoryInfo          : NotSpecified: (:) [], RuntimeException
FullyQualifiedErrorId : RuntimeException
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}

CodePudding user response:

The DivideByZeroException instance is in stored in the .InnerException property of the .Exception property value of the System.Management.Automation.ErrorRecord instance stored in $Error[0], reflecting the most recent error:

PS> try { 1 / 0 } catch {}; $Error[0].Exception.InnerException.GetType().FullName

System.DivideByZeroException

That is, the RuntimeException wraps the DivideByZeroException exception.

Seemingly, because you're using a type-qualified catch block, inside that catch block, the [ErrorRecord] instance reflected in the automatic $_ variable contains the specified exception directly in .Exception - unlike in the corresponding entry in the automatic $Error variable:

PS> try { 1 / 0 } catch [DivideByZeroException] { 
      $_.Exception.GetType().FullName; 
      $Error[0].Exception.GetType().FullName 
    }

System.DivideByZeroException                  # type of $_.Exception
System.Management.Automation.RuntimeException # type of $Error[0].Exception

In other words:

  • In an unqualified catch block, $_ is equivalent to $Error[0] (the latter can also be accessed later), and contains the (outer) exception in .Exception and - if applicable - an inner exception in .Exception.InnerException.

  • In a type-qualified catch block, you can catch an inner exception - as (also later) reflected in $Error[0].Exception.InnerException - directly, in which case $_.Exception inside the qualified catch block contains that inner exception.

  • Related