1
- <#
2
- if (@('NativeCommandErrorMessage','NativeCommandError') -notcontains $_.FullyQualifiedErrorId -and @('CategoryView','ConciseView','DetailedView') -notcontains $ErrorView)
3
- {
4
- $myinv = $_.InvocationInfo
5
- if ($myinv -and $myinv.MyCommand)
6
- {
7
- switch -regex ( $myinv.MyCommand.CommandType )
8
- {
9
- ([System.Management.Automation.CommandTypes]::ExternalScript)
10
- {
11
- if ($myinv.MyCommand.Path)
12
- {
13
- $myinv.MyCommand.Path + ' : '
14
- }
15
-
16
- break
17
- }
18
-
19
- ([System.Management.Automation.CommandTypes]::Script)
20
- {
21
- if ($myinv.MyCommand.ScriptBlock)
22
- {
23
- $myinv.MyCommand.ScriptBlock.ToString() + ' : '
24
- }
25
-
26
- break
27
- }
28
- default
29
- {
30
- if ($myinv.InvocationName -match '^[&\.]?$')
31
- {
32
- if ($myinv.MyCommand.Name)
33
- {
34
- $myinv.MyCommand.Name + ' : '
35
- }
36
- }
37
- else
38
- {
39
- $myinv.InvocationName + ' : '
40
- }
41
-
42
- break
43
- }
44
- }
45
- }
46
- elseif ($myinv -and $myinv.InvocationName)
47
- {
48
- $myinv.InvocationName + ' : '
49
- }
50
- }
51
-
52
-
53
1
Set-StrictMode - Off
54
2
$ErrorActionPreference = ' Stop'
55
3
trap { ' Error found in error view definition: ' + $_.Exception.Message }
@@ -64,6 +12,7 @@ if ($Host.UI.SupportsVirtualTerminal -and ([string]::IsNullOrEmpty($env:__Suppre
64
12
$errorColor = $PSStyle.Formatting.Error
65
13
$accentColor = $PSStyle.Formatting.ErrorAccent
66
14
}
15
+
67
16
function Get-ConciseViewPositionMessage {
68
17
69
18
# returns a string cut to last whitespace
@@ -82,17 +31,30 @@ function Get-ConciseViewPositionMessage {
82
31
$message = ' '
83
32
$prefix = ' '
84
33
34
+ # Handle case where there is a TargetObject from a Pester `Should` assertion failure and we can show the error at the target rather than the script source
35
+ # Note that in some versions, this is a Dictionary<,> and in others it's a hashtable. So we explicitly cast to a shared interface in the method invocation
36
+ # to force using `IDictionary.Contains`. Hashtable does have it's own `ContainKeys` as well, but if they ever opt to use a custom `IDictionary`, that may not.
37
+ $useTargetObject = $null -ne $err.TargetObject -and
38
+ $err.TargetObject -is [System.Collections.IDictionary ] -and
39
+ ([System.Collections.IDictionary ]$err.TargetObject ).Contains(' Line' ) -and
40
+ ([System.Collections.IDictionary ]$err.TargetObject ).Contains(' LineText' )
41
+
85
42
# The checks here determine if we show line detailed error information:
86
43
# - check if `ParserError` and comes from PowerShell which eventually results in a ParseException, but during this execution it's an ErrorRecord
44
+ $isParseError = $err.CategoryInfo.Category -eq ' ParserError' -and
45
+ $err.Exception -is [System.Management.Automation.ParentContainsErrorRecordException ]
46
+
87
47
# - check if invocation is a script or multiple lines in the console
48
+ $isMultiLineOrExternal = $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1
49
+
88
50
# - check that it's not a script module as expectation is that users don't want to see the line of error within a module
89
- if ((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1) -and $myinv.ScriptName -notmatch '\.psm1$') {
90
- $useTargetObject = $false
51
+ $shouldShowLineDetail = ($isParseError -or $isMultiLineOrExternal ) -and
52
+ $myinv.ScriptName -notmatch ' \.psm1$'
53
+
54
+ if ($useTargetObject -or $shouldShowLineDetail ) {
91
55
92
- # Handle case where there is a TargetObject and we can show the error at the target rather than the script source
93
- if ($_.TargetObject.Line -and $_.TargetObject.LineText) {
94
- $posmsg = "${resetcolor}$($_.TargetObject.File)${newline}"
95
- $useTargetObject = $true
56
+ if ($useTargetObject ) {
57
+ $posmsg = " ${resetcolor} $ ( $err.TargetObject.File ) ${newline} "
96
58
}
97
59
elseif ($myinv.ScriptName ) {
98
60
if ($env: TERM_PROGRAM -eq ' vscode' ) {
@@ -108,8 +70,8 @@ function Get-ConciseViewPositionMessage {
108
70
}
109
71
110
72
if ($useTargetObject ) {
111
- $scriptLineNumber = $_ .TargetObject.Line
112
- $scriptLineNumberLength = $_ .TargetObject.Line.ToString().Length
73
+ $scriptLineNumber = $err .TargetObject.Line
74
+ $scriptLineNumberLength = $err .TargetObject.Line.ToString ().Length
113
75
}
114
76
else {
115
77
$scriptLineNumber = $myinv.ScriptLineNumber
@@ -181,7 +143,7 @@ function Get-ConciseViewPositionMessage {
181
143
182
144
# if rendering line information, break up the message if it's wider than the console
183
145
if ($myinv -and $myinv.ScriptName -or $err.CategoryInfo.Category -eq ' ParserError' ) {
184
- $prefixLength = "$([char]27)]8;;{0}`a{1}$([char]27)]8;;`a" -f $pwd, $pwd ::new($prefix).ContentLength
146
+ $prefixLength = [ System.Management.Automation.Internal.StringDecorated ] ::new($prefix ).ContentLength
185
147
$prefixVtLength = $prefix.Length - $prefixLength
186
148
187
149
# replace newlines in message so it lines up correct
@@ -232,8 +194,8 @@ function Get-ConciseViewPositionMessage {
232
194
$reason = $myinv.MyCommand
233
195
}
234
196
# If it's a scriptblock, better to show the command in the scriptblock that had the error
235
- elseif ($_ .CategoryInfo.Activity) {
236
- $reason = $_ .CategoryInfo.Activity
197
+ elseif ($err .CategoryInfo.Activity ) {
198
+ $reason = $err .CategoryInfo.Activity
237
199
}
238
200
elseif ($myinv.MyCommand ) {
239
201
$reason = $myinv.MyCommand
@@ -264,9 +226,8 @@ if ($err.FullyQualifiedErrorId -eq 'NativeCommandErrorMessage' -or $err.FullyQua
264
226
return " ${errorColor} $ ( $err.Exception.Message ) ${resetcolor} "
265
227
}
266
228
267
- $myinv = $err.InvocationInfo
268
229
if ($ErrorView -eq ' DetailedView' ) {
269
- $message = Get-Error
230
+ $message = Get-Error | Out-String
270
231
return " ${errorColor}${message}${resetcolor} "
271
232
}
272
233
@@ -281,21 +242,29 @@ if ($ErrorView -eq 'ConciseView') {
281
242
}
282
243
elseif ($myinv -and ($myinv.MyCommand -or ($err.CategoryInfo.Category -ne ' ParserError' ))) {
283
244
$posmsg = $myinv.PositionMessage
284
- }
285
-
286
- if ($posmsg -ne '') {
287
- $posmsg = $newline + $posmsg
245
+ if ($posmsg -ne ' ' ) {
246
+ $posmsg = $newline + $posmsg
247
+ }
288
248
}
289
249
290
250
if ($err.PSMessageDetails ) {
291
251
$posmsg = ' : ' + $err.PSMessageDetails + $posmsg
292
252
}
293
253
294
254
if ($ErrorView -eq ' ConciseView' ) {
255
+ $recommendedAction = $_.ErrorDetails.RecommendedAction
256
+ if (-not [String ]::IsNullOrWhiteSpace($recommendedAction )) {
257
+ $recommendedAction = $newline +
258
+ ${errorColor} +
259
+ ' Recommendation: ' +
260
+ $recommendedAction +
261
+ ${resetcolor}
262
+ }
263
+
295
264
if ($err.PSMessageDetails ) {
296
265
$posmsg = " ${errorColor}${posmsg} "
297
266
}
298
- return $posmsg
267
+ return $posmsg + $recommendedAction
299
268
}
300
269
301
270
$indent = 4
@@ -330,6 +299,4 @@ $finalMsg = if ($err.ErrorDetails.Message) {
330
299
$err.Exception.Message + $posmsg
331
300
}
332
301
333
- "${errorColor}${finalMsg}${resetcolor}"
334
-
335
- #>
302
+ " ${errorColor}${finalMsg}${resetcolor} "
0 commit comments