Whenever you deal with error objects, you may want to use the following PowerShell function: Get-ErrorInfo. It accepts any number of error records, and turns them into easily usable error information objects:
function Get-ErrorInfo { param ( [System.Management.Automation.ErrorRecord] [Parameter(Mandatory = $true, ValueFromPipeline=$true)] $ErrorInfo ) process { $hash = [Ordered]@{ ScriptName = $ErrorInfo.InvocationInfo.ScriptName ErrorMessage = $ErrorInfo.Exception.Message LineNumber = $ErrorInfo.InvocationInfo.ScriptLineNumber ColumnNumber = $ErrorInfo.InvocationInfo.OffsetInLine Category = $ErrorInfo.CategoryInfo.Category ErrorReason = $ErrorInfo.CategoryInfo.Reason Target = $ErrorInfo.CategoryInfo.TargetName StackTrace = $ErrorInfo.Exception.StackTrace } New-Object -TypeName PSObject -Property $hash } }
You can try this with $error, for example (provided you had some errors in your current PowerShell session):
PS> $Error | Get-ErrorInfo ScriptName : C:\Users\Tobias\Documents\WindowsPowerShell\Modules\PSAlphaFS\1.0.0.0\PSAlphaFS.psm1 ErrorMessage : An error occurred while enumerating through a collection: (5) Access is denied: [\\?\C:\Users\Tobias\Application Data]. LineNumber : 318 ColumnNumber : 40 Category : InvalidOperation ErrorReason : RuntimeException Target : Alphaleonis.Win32.Filesystem.FindFileSystemEntryInfo+d__3`1[System.String] StackTrace : at System.Management.Automation.EnumerableOps.MoveNext(ExecutionContext context, IEnumerator enumerator) at System.Management.Automation.EnumerableOps.ToArray(IEnumerator enumerator) at System.Management.Automation.Interpreter.DynamicInstruction`2.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) ScriptName : C:\Users\Tobias\Documents\WindowsPowerShell\Modules\PSAlphaFS\1.0.0.0\PSAlphaFS.psm1 ErrorMessage : An error occurred while enumerating through a collection: (5) Access is denied: [\\?\C:\Users\Tobias\Application Data]. LineNumber : 318 ColumnNumber : 40 Category : InvalidOperation ErrorReason : RuntimeException Target : Alphaleonis.Win32.Filesystem.FindFileSystemEntryInfo+d__3`1[System.String] StackTrace : at System.Management.Automation.EnumerableOps.MoveNext(ExecutionContext context, IEnumerator enumerator) at System.Management.Automation.EnumerableOps.ToArray(IEnumerator enumerator) at System.Management.Automation.Interpreter.DynamicInstruction`2.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) ...
You can use it inside any error handler (try or trap): pipe $_ to Get-ErrorInfo. And you can use it with error variables:
$files = Get-ChildItem -Path $env:windir -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue -ErrorVariable myError $myError | Get-ErrorInfo | Select-Object -Property ErrorReason, Target
The result would look similar to this and show the files that were inaccessible:
PS> $myError | Get-ErrorInfo | Select-Object -Property ErrorReason, Target ErrorReason Target ----------- ------ UnauthorizedAccessException C:\WINDOWS\appcompat\Programs UnauthorizedAccessException C:\WINDOWS\CSC\v2.0.6 UnauthorizedAccessException C:\WINDOWS\InfusedApps UnauthorizedAccessException C:\WINDOWS\LiveKernelReports UnauthorizedAccessException C:\WINDOWS\Logs\HomeGroup