@@ -9,40 +9,38 @@ function GetListRecursive {
99 [int ]$indent = 0 ,
1010 [int ]$depth = 1
1111 )
12- Write-Information " ENTER GetListRecursive END $ ( $InputObject.GetType ().FullName) $indent $depth " - Tags ' Trace' , ' Enter' , ' GetListRecursive'
13- Write-Information (Get-PSCallStack ) - Tags ' Trace' , ' StackTrace' , ' GetListRecursive'
1412 $output = [System.Text.StringBuilder ]::new()
15- $prefix = ' ' * $indent
13+ $padding = ' ' * $indent
1614
1715 $expandTypes = @ (
1816 ' Microsoft.Rest.HttpRequestMessageWrapper'
1917 ' Microsoft.Rest.HttpResponseMessageWrapper'
2018 ' System.Management.Automation.InvocationInfo'
2119 )
2220
23- # The built-in DetailedView aligns all the ":" characters, so we need to find the longest property name
24- $propLength = 0
25- foreach ($prop in $InputObject.PSObject.Properties ) {
26- if ($null -ne $prop.Value -and $prop.Value -ne [string ]::Empty -and $prop.Name.Length -gt $propLength ) {
27- $propLength = $prop.Name.Length
28- }
29- }
21+ # The built-in DetailedView aligns all the ":" characters, but it's awful
3022
3123 $addedProperty = $false
3224 foreach ($prop in $InputObject.PSObject.Properties ) {
25+ # PowerShell creates an ErrorRecord property on Exceptions that points back to the parent ErrorRecord.
26+ # This is basically a circular reference that causes repeated informtion, so we're going to skip them
27+ if ($prop.Value -is [System.Management.Automation.ErrorRecord ] -and $depth -ge 2 ) {
28+ continue
29+ }
3330 # don't show empty properties or our added property for $error[index]
3431 if ($null -ne $prop.Value -and $prop.Value -ne [string ]::Empty -and $prop.Value.count -gt 0 -and $prop.Name -ne ' PSErrorIndex' ) {
3532 $addedProperty = $true
36- $null = $output.Append ($prefix )
33+ $null = $output.Append ($padding )
3734 $null = $output.Append ($accentColor )
3835 $null = $output.Append ($prop.Name )
39- $null = $output.Append (' ' , ($propLength - $prop.Name.Length ))
40- $null = $output.Append (' : ' )
36+ $null = $output.Append (' : ' )
4137 $null = $output.Append ($resetColor )
4238
43- $newIndent = $indent + 2
39+ [int ]$nextIndent = $indent + 2
40+ [int ]$nextDepth = $depth + 1
41+ $nextPadding = ' ' * $nextIndent
4442
45- # only show nested objects that are Exceptions, ErrorRecords, or types defined in $expandTypes and types not in $ignoreTypes
43+ # only show nested objects that are Exceptions, ErrorRecords, or types defined in $expandTypes
4644 if ($prop.Value -is [Exception ] -or
4745 $prop.Value -is [System.Management.Automation.ErrorRecord ] -or
4846 $expandTypes -contains $prop.TypeNameOfValue -or
@@ -51,16 +49,12 @@ function GetListRecursive {
5149 if ($depth -ge $maxDepth ) {
5250 $null = $output.Append ($ellipsis )
5351 } else {
52+ # For Exceptions, add a fake "Type" property
5453 if ($prop.Value -is [Exception ]) {
55- $null = $output.Append ($newline )
56- $null = $output.Append ((
57- GetListRecursive ([PSCustomObject ]@ {
58- " Type" = $errorAccentColor + $prop.Value.GetType ().FullName + $resetColor
59- }) $newIndent ($depth + 1 )
60- ))
54+ $null = $output.Append (( $accentColor + " [" + $prop.Value.GetType ().FullName + " ]" + $resetColor ))
6155 }
6256 $null = $output.Append ($newline )
63- $null = $output.Append ((GetListRecursive $prop.Value $newIndent ( $depth + 1 ) ))
57+ $null = $output.Append ((GetListRecursive $prop.Value $nextIndent $nextDepth ))
6458 }
6559 } elseif ($prop.Name -eq ' TargetSite' -and $prop.Value.GetType ().Name -eq ' RuntimeMethodInfo' ) {
6660 # `TargetSite` has many members that are not useful visually, so we have a reduced view of the relevant members
@@ -75,28 +69,34 @@ function GetListRecursive {
7569 }
7670
7771 $null = $output.Append ($newline )
78- $null = $output.Append ((GetListRecursive $targetSite $newIndent ( $depth + 1 ) ))
72+ $null = $output.Append ((GetListRecursive $targetSite $nextIndent $nextDepth ))
7973 }
8074 } elseif ($prop.Name -eq ' StackTrace' ) {
81- # `StackTrace` is handled specifically because the lines are typically long but necessary so they are left justified without additional indentation
82- # for a stacktrace which is usually quite wide with info, we left justify it
75+ # StackTrace is handled specifically because the lines are typically long but we can't trucate them, so we don't indent it any more
8376 $null = $output.Append ($newline )
84- $null = $output.Append ($prop.Value )
77+ # $null = $output.Append($prop.Value)
78+ $Wrap = @ {
79+ Width = $Host.UI.RawUI.BufferSize.Width - 2
80+ IndentPadding = " "
81+ HangingIndent = " "
82+ }
83+ $null = $output.Append (($prop.Value | WrapString @Wrap ))
84+ } elseif ($prop.Name -eq ' HResult' ) {
85+ # `HResult` is handled specifically so we can format it in hex
86+ # $null = $output.Append($newline)
87+ $null = $output.Append (" 0x{0:x} ({0})" -f $prop.Value )
88+ } elseif ($prop.Name -eq ' PipelineIterationInfo' ) {
89+ # I literally have no idea what use this is
90+ $null = $output.Append ($prop.Value -join ' , ' )
8591 } elseif ($prop.Value.GetType ().Name.StartsWith(' Dictionary' ) -or $prop.Value.GetType ().Name -eq ' Hashtable' ) {
86- # Dictionary and Hashtable we want to show as Key/Value pairs, we don't do the extra whitespace alignment here
87- $isFirstElement = $true
92+ # Dictionary and Hashtable we want to show as Key/Value pairs
93+ $null = $output .Append ( $newline )
8894 foreach ($key in $prop.Value.Keys ) {
89- if ($isFirstElement ) {
90- $null = $output.Append ($newline )
91- }
92-
9395 if ($key -eq ' Authorization' ) {
94- $null = $output.Append (" ${prefix} ${accentColor}${key} : ${resetColor}${ellipsis}${newline} " )
96+ $null = $output.Append (" ${nextPadding} ${accentColor}${key} : ${resetColor}${ellipsis}${newline} " )
9597 } else {
96- $null = $output.Append (" ${prefix} ${accentColor}${key} : ${resetColor} $ ( $prop.Value [$key ]) ${newline} " )
98+ $null = $output.Append (" ${nextPadding} ${accentColor}${key} : ${resetColor} $ ( $prop.Value [$key ]) ${newline} " )
9799 }
98-
99- $isFirstElement = $false
100100 }
101101 } elseif (! ($prop.Value -is [System.String ]) -and $null -ne $prop.Value.GetType ().GetInterface(' IEnumerable' ) -and $prop.Name -ne ' Data' ) {
102102 # if the object implements IEnumerable and not a string, we try to show each object
@@ -108,41 +108,43 @@ function GetListRecursive {
108108 $isFirstElement = $true
109109 foreach ($value in $prop.Value ) {
110110 $null = $output.Append ($newline )
111- if (! $isFirstElement ) {
112- $null = $output.Append ($newline )
111+
112+ if ($value -is [Type ]) {
113+ # Just show the typename instead of it as an object
114+ $null = $output.Append (" ${nextPadding} [$ ( $value.ToString ()) ]" )
115+ } elseif ($value -is [string ] -or $value.GetType ().IsPrimitive) {
116+ $null = $output.Append (" ${nextPadding}${value} " )
117+ } else {
118+ if (! $isFirstElement ) {
119+ $null = $output.Append ($newline )
120+ }
121+ $null = $output.Append ((GetListRecursive $value $nextIndent $nextDepth ))
113122 }
114- $null = $output.Append ((GetListRecursive $value $newIndent ($depth + 1 )))
115123 $isFirstElement = $false
116124 }
117125 }
126+ } elseif ($prop.Value -is [Type ]) {
127+ # Just show the typename instead of it as an object
128+ $null = $output.Append (" [$ ( $prop.Value.ToString ()) ]" )
118129 } else {
119130 # Anything else, we convert to string.
120131 # ToString() can throw so we use LanguagePrimitives.TryConvertTo() to hide a convert error
121132 $value = $null
122133 if ([System.Management.Automation.LanguagePrimitives ]::TryConvertTo($prop.Value , [string ], [ref ]$value ) -and $null -ne $value ) {
123134 $value = $value.Trim ()
124- if ($prop.Name -eq ' PositionMessage' ) {
135+ if ($InputObject -is [System.Management.Automation.InvocationInfo ] -and $prop.Name -eq ' PositionMessage' ) {
136+ # Make the underline red
125137 $value = $value.Insert ($value.IndexOf (' ~' ), $errorColor )
126- } elseif ($prop.Name -eq ' Message' ) {
138+ } elseif ( ($InputObject -is [System.Management.Automation.ErrorRecord ] -or
139+ $InputObject -is [System.Exception ]) -and $prop.Name -in ' Message' , ' FullyQualifiedErrorId' , ' CategoryInfo' ) {
127140 $value = $errorColor + $value
128141 }
129-
130- $isFirstLine = $true
131- if ($value.Contains ($newline )) {
132- # the 3 is to account for ' : '
133- # $valueIndent = ' ' * ($prop.Name.Length + 2)
134- $valueIndent = ' ' * ($propLength + 3 )
135- # need to trim any extra whitespace already in the text
136- foreach ($line in $value.Split ($newline )) {
137- if (! $isFirstLine ) {
138- $null = $output.Append (" ${newline}${prefix}${valueIndent} " )
139- }
140- $null = $output.Append ($line.Trim ())
141- $isFirstLine = $false
142- }
143- } else {
144- $null = $output.Append ($value )
142+ $Wrap = @ {
143+ Width = $Host.UI.RawUI.BufferSize.Width - 2
144+ IndentPadding = " " * ($nextIndent + $prop.Name.Length )
145145 }
146+
147+ $null = $output.Append (($value | WrapString @Wrap ).TrimStart())
146148 }
147149 }
148150
0 commit comments