@@ -9,40 +9,38 @@ function GetListRecursive {
9
9
[int ]$indent = 0 ,
10
10
[int ]$depth = 1
11
11
)
12
- Write-Information " ENTER GetListRecursive END $ ( $InputObject.GetType ().FullName) $indent $depth " - Tags ' Trace' , ' Enter' , ' GetListRecursive'
13
- Write-Information (Get-PSCallStack ) - Tags ' Trace' , ' StackTrace' , ' GetListRecursive'
14
12
$output = [System.Text.StringBuilder ]::new()
15
- $prefix = ' ' * $indent
13
+ $padding = ' ' * $indent
16
14
17
15
$expandTypes = @ (
18
16
' Microsoft.Rest.HttpRequestMessageWrapper'
19
17
' Microsoft.Rest.HttpResponseMessageWrapper'
20
18
' System.Management.Automation.InvocationInfo'
21
19
)
22
20
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
30
22
31
23
$addedProperty = $false
32
24
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
+ }
33
30
# don't show empty properties or our added property for $error[index]
34
31
if ($null -ne $prop.Value -and $prop.Value -ne [string ]::Empty -and $prop.Value.count -gt 0 -and $prop.Name -ne ' PSErrorIndex' ) {
35
32
$addedProperty = $true
36
- $null = $output.Append ($prefix )
33
+ $null = $output.Append ($padding )
37
34
$null = $output.Append ($accentColor )
38
35
$null = $output.Append ($prop.Name )
39
- $null = $output.Append (' ' , ($propLength - $prop.Name.Length ))
40
- $null = $output.Append (' : ' )
36
+ $null = $output.Append (' : ' )
41
37
$null = $output.Append ($resetColor )
42
38
43
- $newIndent = $indent + 2
39
+ [int ]$nextIndent = $indent + 2
40
+ [int ]$nextDepth = $depth + 1
41
+ $nextPadding = ' ' * $nextIndent
44
42
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
46
44
if ($prop.Value -is [Exception ] -or
47
45
$prop.Value -is [System.Management.Automation.ErrorRecord ] -or
48
46
$expandTypes -contains $prop.TypeNameOfValue -or
@@ -51,16 +49,12 @@ function GetListRecursive {
51
49
if ($depth -ge $maxDepth ) {
52
50
$null = $output.Append ($ellipsis )
53
51
} else {
52
+ # For Exceptions, add a fake "Type" property
54
53
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 ))
61
55
}
62
56
$null = $output.Append ($newline )
63
- $null = $output.Append ((GetListRecursive $prop.Value $newIndent ( $depth + 1 ) ))
57
+ $null = $output.Append ((GetListRecursive $prop.Value $nextIndent $nextDepth ))
64
58
}
65
59
} elseif ($prop.Name -eq ' TargetSite' -and $prop.Value.GetType ().Name -eq ' RuntimeMethodInfo' ) {
66
60
# `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 {
75
69
}
76
70
77
71
$null = $output.Append ($newline )
78
- $null = $output.Append ((GetListRecursive $targetSite $newIndent ( $depth + 1 ) ))
72
+ $null = $output.Append ((GetListRecursive $targetSite $nextIndent $nextDepth ))
79
73
}
80
74
} 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
83
76
$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 ' , ' )
85
91
} 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 )
88
94
foreach ($key in $prop.Value.Keys ) {
89
- if ($isFirstElement ) {
90
- $null = $output.Append ($newline )
91
- }
92
-
93
95
if ($key -eq ' Authorization' ) {
94
- $null = $output.Append (" ${prefix} ${accentColor}${key} : ${resetColor}${ellipsis}${newline} " )
96
+ $null = $output.Append (" ${nextPadding} ${accentColor}${key} : ${resetColor}${ellipsis}${newline} " )
95
97
} 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} " )
97
99
}
98
-
99
- $isFirstElement = $false
100
100
}
101
101
} elseif (! ($prop.Value -is [System.String ]) -and $null -ne $prop.Value.GetType ().GetInterface(' IEnumerable' ) -and $prop.Name -ne ' Data' ) {
102
102
# if the object implements IEnumerable and not a string, we try to show each object
@@ -108,41 +108,43 @@ function GetListRecursive {
108
108
$isFirstElement = $true
109
109
foreach ($value in $prop.Value ) {
110
110
$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 ))
113
122
}
114
- $null = $output.Append ((GetListRecursive $value $newIndent ($depth + 1 )))
115
123
$isFirstElement = $false
116
124
}
117
125
}
126
+ } elseif ($prop.Value -is [Type ]) {
127
+ # Just show the typename instead of it as an object
128
+ $null = $output.Append (" [$ ( $prop.Value.ToString ()) ]" )
118
129
} else {
119
130
# Anything else, we convert to string.
120
131
# ToString() can throw so we use LanguagePrimitives.TryConvertTo() to hide a convert error
121
132
$value = $null
122
133
if ([System.Management.Automation.LanguagePrimitives ]::TryConvertTo($prop.Value , [string ], [ref ]$value ) -and $null -ne $value ) {
123
134
$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
125
137
$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' ) {
127
140
$value = $errorColor + $value
128
141
}
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 )
145
145
}
146
+
147
+ $null = $output.Append (($value | WrapString @Wrap ).TrimStart())
146
148
}
147
149
}
148
150
0 commit comments