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-
531Set-StrictMode - Off
542$ErrorActionPreference = ' Stop'
553trap { ' Error found in error view definition: ' + $_.Exception.Message }
@@ -64,6 +12,7 @@ if ($Host.UI.SupportsVirtualTerminal -and ([string]::IsNullOrEmpty($env:__Suppre
6412 $errorColor = $PSStyle.Formatting.Error
6513 $accentColor = $PSStyle.Formatting.ErrorAccent
6614}
15+
6716function Get-ConciseViewPositionMessage {
6817
6918 # returns a string cut to last whitespace
@@ -82,17 +31,30 @@ function Get-ConciseViewPositionMessage {
8231 $message = ' '
8332 $prefix = ' '
8433
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+
8542 # The checks here determine if we show line detailed error information:
8643 # - 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+
8747 # - check if invocation is a script or multiple lines in the console
48+ $isMultiLineOrExternal = $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1
49+
8850 # - 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 ) {
9155
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} "
9658 }
9759 elseif ($myinv.ScriptName ) {
9860 if ($env: TERM_PROGRAM -eq ' vscode' ) {
@@ -108,8 +70,8 @@ function Get-ConciseViewPositionMessage {
10870 }
10971
11072 if ($useTargetObject ) {
111- $scriptLineNumber = $_ .TargetObject.Line
112- $scriptLineNumberLength = $_ .TargetObject.Line.ToString().Length
73+ $scriptLineNumber = $err .TargetObject.Line
74+ $scriptLineNumberLength = $err .TargetObject.Line.ToString ().Length
11375 }
11476 else {
11577 $scriptLineNumber = $myinv.ScriptLineNumber
@@ -181,7 +143,7 @@ function Get-ConciseViewPositionMessage {
181143
182144 # if rendering line information, break up the message if it's wider than the console
183145 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
185147 $prefixVtLength = $prefix.Length - $prefixLength
186148
187149 # replace newlines in message so it lines up correct
@@ -232,8 +194,8 @@ function Get-ConciseViewPositionMessage {
232194 $reason = $myinv.MyCommand
233195 }
234196 # 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
237199 }
238200 elseif ($myinv.MyCommand ) {
239201 $reason = $myinv.MyCommand
@@ -264,9 +226,8 @@ if ($err.FullyQualifiedErrorId -eq 'NativeCommandErrorMessage' -or $err.FullyQua
264226 return " ${errorColor} $ ( $err.Exception.Message ) ${resetcolor} "
265227}
266228
267- $myinv = $err.InvocationInfo
268229if ($ErrorView -eq ' DetailedView' ) {
269- $message = Get-Error
230+ $message = Get-Error | Out-String
270231 return " ${errorColor}${message}${resetcolor} "
271232}
272233
@@ -281,21 +242,29 @@ if ($ErrorView -eq 'ConciseView') {
281242}
282243elseif ($myinv -and ($myinv.MyCommand -or ($err.CategoryInfo.Category -ne ' ParserError' ))) {
283244 $posmsg = $myinv.PositionMessage
284- }
285-
286- if ($posmsg -ne '') {
287- $posmsg = $newline + $posmsg
245+ if ($posmsg -ne ' ' ) {
246+ $posmsg = $newline + $posmsg
247+ }
288248}
289249
290250if ($err.PSMessageDetails ) {
291251 $posmsg = ' : ' + $err.PSMessageDetails + $posmsg
292252}
293253
294254if ($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+
295264 if ($err.PSMessageDetails ) {
296265 $posmsg = " ${errorColor}${posmsg} "
297266 }
298- return $posmsg
267+ return $posmsg + $recommendedAction
299268}
300269
301270$indent = 4
@@ -330,6 +299,4 @@ $finalMsg = if ($err.ErrorDetails.Message) {
330299 $err.Exception.Message + $posmsg
331300}
332301
333- "${errorColor}${finalMsg}${resetcolor}"
334-
335- #>
302+ " ${errorColor}${finalMsg}${resetcolor} "
0 commit comments