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 qualifiedcatch
block contains that inner exception.