Whenever PowerShell encounters an error, it emits an Error Record with detailed information about the problem. Unfortunately, these objects are a bit cryptic and won’t show all of their information by default. To get to the beef, a function like the below is of invaluable help:
function ConvertFrom-ErrorRecord { param ( # we receive either a legit error record... [Management.Automation.ErrorRecord[]] [Parameter( Mandatory,ValueFromPipeline, ParameterSetName='ErrorRecord')] $ErrorRecord, # ...or a special stop exception which is raised by # cmdlets with -ErrorAction Stop [Management.Automation.ActionPreferenceStopException[]] [Parameter( Mandatory,ValueFromPipeline, ParameterSetName='StopException')] $Exception ) process { # if we received a stop exception in $Exception, # the error record is to be found inside of it # in all other cases, $ErrorRecord was received # directly if ($PSCmdlet.ParameterSetName -eq 'StopException') { $ErrorRecord = $Exception.ErrorRecord } # compose a new object out of the interesting properties # found in the error record object $ErrorRecord | ForEach-Object { [PSCustomObject]@{ Exception = $_.Exception.Message Reason = $_.CategoryInfo.Reason Target = $_.CategoryInfo.TargetName Script = $_.InvocationInfo.ScriptName Line = $_.InvocationInfo.ScriptLineNumber Column = $_.InvocationInfo.OffsetInLine } } } }
With it, you can decipher the error information collected in $error:
PS C:\> $Error | ConvertFrom-ErrorRecord | Out-GridView
You can as well use it in try..catch blocks:
try { Get-Service -Name foo -ErrorAction Stop } catch { $_ | ConvertFrom-ErrorRecord }
The result will be similar to this:
Exception : Cannot find any service with service name 'foo'. Reason : ServiceCommandException Target : foo Script : Line : 5 Column : 3
And you can it even with the –ErrorVariable common parameter which collects all error records that occur while a cmdlet runs:
$r = Get-ChildItem -Path $env:windir -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue -ErrorVariable test $test | ConvertFrom-ErrorRecord
The result again will be similar to this:
Exception : Access to the path 'C:\Windows\AppCompat\Appraiser\Telemetry' is denied. Reason : UnauthorizedAccessException Target : C:\Windows\AppCompat\Appraiser\Telemetry Script : Line : 3 Column : 6 Exception : Access to the path 'C:\Windows\AppCompat\Programs' is denied. Reason : UnauthorizedAccessException Target : C:\Windows\AppCompat\Programs Script : Line : 3 Column : 6 Exception : Access to the path 'C:\Windows\CSC\v2.0.6' is denied. Reason : UnauthorizedAccessException Target : C:\Windows\CSC\v2.0.6 Script : Line : 3 Column : 6 ...