250 lines
12 KiB
PowerShell
250 lines
12 KiB
PowerShell
Function Resolve-Error {
|
|
<#
|
|
.SYNOPSIS
|
|
Enumerate error record details.
|
|
|
|
.DESCRIPTION
|
|
Enumerate an error record, or a collection of error record, properties. By default, the details
|
|
for the last error will be enumerated.
|
|
|
|
.PARAMETER ErrorRecord
|
|
The error record to resolve. The default error record is the lastest one: $global:Error[0].
|
|
This parameter will also accept an array of error records.
|
|
|
|
.PARAMETER Property
|
|
The list of properties to display from the error record. Use "*" to display all properties.
|
|
Default list of error properties is: Message, FullyQualifiedErrorId, ScriptStackTrace, PositionMessage, InnerException
|
|
|
|
Below is a list of all of the possible available properties on the error record:
|
|
|
|
Error Record: Error Invocation: Error Exception: Error Inner Exception(s):
|
|
$_ $_.InvocationInfo $_.Exception $_.Exception.InnerException
|
|
------------- ----------------- ---------------- ---------------------------
|
|
writeErrorStream MyCommand ErrorRecord Data
|
|
PSMessageDetails BoundParameters ItemName HelpLink
|
|
Exception UnboundArguments SessionStateCategory HResult
|
|
TargetObject ScriptLineNumber StackTrace InnerException
|
|
CategoryInfo OffsetInLine WasThrownFromThrowStatement Message
|
|
FullyQualifiedErrorId HistoryId Message Source
|
|
ErrorDetails ScriptName Data StackTrace
|
|
InvocationInfo Line InnerException TargetSite
|
|
ScriptStackTrace PositionMessage TargetSite
|
|
PipelineIterationInfo PSScriptRoot HelpLink
|
|
PSCommandPath Source
|
|
InvocationName HResult
|
|
PipelineLength
|
|
PipelinePosition
|
|
ExpectingInput
|
|
CommandOrigin
|
|
DisplayScriptPosition
|
|
|
|
.PARAMETER GetErrorRecord
|
|
Get error record details as represented by $_
|
|
Default is to display details. To skip details, specify -GetErrorRecord $false
|
|
|
|
.PARAMETER GetErrorInvocation
|
|
Get error record invocation information as represented by $_.InvocationInfo
|
|
Default is to display details. To skip details, specify -GetErrorInvocation $false
|
|
|
|
.PARAMETER GetErrorException
|
|
Get error record exception details as represented by $_.Exception
|
|
Default is to display details. To skip details, specify -GetErrorException $false
|
|
|
|
.PARAMETER GetErrorInnerException
|
|
Get error record inner exception details as represented by $_.Exception.InnerException.
|
|
Will retrieve all inner exceptions if there is more then one.
|
|
Default is to display details. To skip details, specify -GetErrorInnerException $false
|
|
|
|
.EXAMPLE
|
|
Resolve-Error
|
|
|
|
Get the default error details for the last error
|
|
|
|
.EXAMPLE
|
|
Resolve-Error -ErrorRecord $global:Error[0,1]
|
|
|
|
Get the default error details for the last two errors
|
|
|
|
.EXAMPLE
|
|
Resolve-Error -Property *
|
|
|
|
Get all of the error details for the last error
|
|
|
|
.EXAMPLE
|
|
Resolve-Error -Property InnerException
|
|
|
|
Get the "InnerException" for the last error
|
|
|
|
.EXAMPLE
|
|
Resolve-Error -GetErrorInvocation $false
|
|
|
|
Get the default error details for the last error but exclude the error invocation information
|
|
|
|
.NOTES
|
|
Borrowed from https://stackoverflow.com/questions/795751/can-i-get-detailed-exception-stacktrace-in-powershell
|
|
Please return when done.
|
|
#>
|
|
[CmdletBinding()]
|
|
Param (
|
|
[Parameter(Mandatory=$false, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
|
|
[ValidateNotNullorEmpty()]
|
|
[array]$ErrorRecord,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[ValidateNotNullorEmpty()]
|
|
[string[]]$Property = ('Message','InnerException','FullyQualifiedErrorId','ScriptStackTrace','PositionMessage'),
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[bool]$GetErrorRecord = $true,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[bool]$GetErrorInvocation = $true,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[bool]$GetErrorException = $true,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[bool]$GetErrorInnerException = $true
|
|
)
|
|
|
|
Begin {
|
|
$logLead = (Get-LogLeadName)
|
|
|
|
## If function was called without specifying an error record, then choose the latest error that occured
|
|
if (-not $ErrorRecord) {
|
|
if ($global:Error.Count -eq 0) {
|
|
# The `$Error collection is empty
|
|
Write-Verbose "$logLead : global Error is empty."
|
|
return
|
|
} else {
|
|
Write-Verbose "$logLead : found items in global Error collection. Getting first error."
|
|
[array]$ErrorRecord = $global:Error[0]
|
|
}
|
|
}
|
|
|
|
## Define script block for selecting and filtering the properties on the error object
|
|
[scriptblock]$selectProperty = {
|
|
Param (
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullorEmpty()]
|
|
$InputObject,
|
|
|
|
[Parameter(Mandatory=$true)]
|
|
[ValidateNotNullorEmpty()]
|
|
[string[]]$SelectedProperty
|
|
)
|
|
|
|
Write-Verbose "$logLead : InputObject [$InputObject]"
|
|
Write-Verbose "$logLead : SelectedProperty [$SelectedProperty]"
|
|
[string[]]$objectProperty = $InputObject | Get-Member -MemberType *Property | Select-Object -ExpandProperty Name
|
|
|
|
foreach ($prop in $SelectedProperty) {
|
|
if ($prop -eq '*') {
|
|
[string[]]$propertySelection = $objectProperty
|
|
break
|
|
}
|
|
elseif ($objectProperty -contains $prop) {
|
|
[string[]]$propertySelection += $prop
|
|
}
|
|
}
|
|
return $propertySelection
|
|
}
|
|
|
|
# Initialize variables to avoid error if 'Set-StrictMode' is set
|
|
$logErrorRecordMsg = $null
|
|
$logErrorInvocationMsg = $null
|
|
$logErrorExceptionMsg = $null
|
|
$logErrorMessageTmp = $null
|
|
$logInnerMessage = $null
|
|
} Process {
|
|
foreach ($errRecord in $ErrorRecord) {
|
|
## Capture Error Record
|
|
if ($GetErrorRecord) {
|
|
Write-Verbose "$logLead : Capture Error Record"
|
|
[string[]]$selectedProperties = Invoke-Command -ScriptBlock $selectProperty -ArgumentList $errRecord, $Property
|
|
$logErrorRecordMsg = $errRecord | Select-Object -Property $selectedProperties
|
|
}
|
|
|
|
## Error Invocation Information
|
|
if ($GetErrorInvocation) {
|
|
if ($errRecord.InvocationInfo) {
|
|
Write-Verbose "$logLead : Get Error Invocation Information"
|
|
[string[]]$selectedProperties = Invoke-Command -ScriptBlock $selectProperty -ArgumentList $errRecord.InvocationInfo, $Property
|
|
$logErrorInvocationMsg = $errRecord.InvocationInfo | Select-Object -Property $selectedProperties
|
|
}
|
|
}
|
|
|
|
## Capture Error Exception
|
|
if ($GetErrorException) {
|
|
if ($errRecord.Exception) {
|
|
Write-Verbose "$logLead : Capture Error Exception"
|
|
[string[]]$selectedProperties = Invoke-Command -ScriptBlock $selectProperty -ArgumentList $errRecord.Exception, $Property
|
|
$logErrorExceptionMsg = $errRecord.Exception | Select-Object -Property $selectedProperties
|
|
}
|
|
}
|
|
|
|
## Display properties in the correct order
|
|
if ($Property -eq '*') {
|
|
# If all properties were chosen for display, then arrange them in the order
|
|
# the error object displays them by default.
|
|
Write-Verbose "$logLead : Display all properties"
|
|
if ($logErrorRecordMsg) {[array]$logErrorMessageTmp += $logErrorRecordMsg }
|
|
if ($logErrorInvocationMsg) {[array]$logErrorMessageTmp += $logErrorInvocationMsg}
|
|
if ($logErrorExceptionMsg) {[array]$logErrorMessageTmp += $logErrorExceptionMsg }
|
|
} else {
|
|
# Display selected properties in our custom order
|
|
Write-Verbose "$logLead : Display selected properties in custom order"
|
|
if ($logErrorExceptionMsg) {[array]$logErrorMessageTmp += $logErrorExceptionMsg }
|
|
if ($logErrorRecordMsg) {[array]$logErrorMessageTmp += $logErrorRecordMsg }
|
|
if ($logErrorInvocationMsg) {[array]$logErrorMessageTmp += $logErrorInvocationMsg}
|
|
}
|
|
|
|
if ($logErrorMessageTmp) {
|
|
$logErrorMessage = 'Error Record:'
|
|
$logErrorMessage += "`n-------------"
|
|
$logErrorMsg = $logErrorMessageTmp | Format-List | Out-String
|
|
$logErrorMessage += $logErrorMsg
|
|
}
|
|
|
|
## Capture Error Inner Exception(s)
|
|
if ($GetErrorInnerException) {
|
|
if ($errRecord.Exception -and $errRecord.Exception.InnerException) {
|
|
Write-Verbose "$logLead : Capture Error Inner Exception"
|
|
$logInnerMessage = 'Error Inner Exception(s):'
|
|
$logInnerMessage += "`n-------------------------"
|
|
|
|
$errorInnerException = $errRecord.Exception.InnerException
|
|
$Count = 0
|
|
|
|
while ($errorInnerException) {
|
|
$innerExceptionSeperator = '~' * 40
|
|
|
|
[string[]]$selectedProperties = Invoke-Command -ScriptBlock $selectProperty -ArgumentList $errorInnerException, $Property
|
|
$logErrorInnerExceptionMsg = $errorInnerException | Select-Object -Property $selectedProperties | Format-List | Out-String
|
|
|
|
if ($Count -gt 0) {
|
|
$logInnerMessage += $innerExceptionSeperator
|
|
}
|
|
$logInnerMessage += $logErrorInnerExceptionMsg
|
|
|
|
$Count++
|
|
$errorInnerException = $errorInnerException.InnerException
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($logErrorMessage) { $output += $logErrorMessage }
|
|
if ($logInnerMessage) { $output += $logInnerMessage }
|
|
|
|
Write-Verbose "$logLead : Write output"
|
|
Write-Host $output
|
|
|
|
Write-Verbose "$logLead : Cleanup variables"
|
|
if (Test-Path -Path 'variable:Output' ) { Clear-Variable -Name output }
|
|
if (Test-Path -Path 'variable:LogErrorMessage' ) { Clear-Variable -Name logErrorMessage }
|
|
if (Test-Path -Path 'variable:logInnerMessage' ) { Clear-Variable -Name logInnerMessage }
|
|
if (Test-Path -Path 'variable:logErrorMessageTmp') { Clear-Variable -Name logErrorMessageTmp }
|
|
}
|
|
}
|
|
End {}
|
|
} |