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+ Set-StrictMode -Off
54+ $ErrorActionPreference = 'Stop'
55+ trap { 'Error found in error view definition: ' + $_.Exception.Message }
56+ $newline = [Environment]::Newline
57+
58+ $resetColor = ''
59+ $errorColor = ''
60+ $accentColor = ''
61+
62+ if ($Host.UI.SupportsVirtualTerminal -and ([string]::IsNullOrEmpty($env:__SuppressAnsiEscapeSequences))) {
63+ $resetColor = $PSStyle.Reset
64+ $errorColor = $PSStyle.Formatting.Error
65+ $accentColor = $PSStyle.Formatting.ErrorAccent
66+ }
67+ function Get-ConciseViewPositionMessage {
68+
69+ # returns a string cut to last whitespace
70+ function Get-TruncatedString($string, [int]$length) {
71+
72+ if ($string.Length -le $length) {
73+ return $string
74+ }
75+
76+ return ($string.Substring(0,$length) -split '\s',-2)[0]
77+ }
78+
79+ $posmsg = ''
80+ $headerWhitespace = ''
81+ $offsetWhitespace = ''
82+ $message = ''
83+ $prefix = ''
84+
85+ # The checks here determine if we show line detailed error information:
86+ # - check if `ParserError` and comes from PowerShell which eventually results in a ParseException, but during this execution it's an ErrorRecord
87+ # - check if invocation is a script or multiple lines in the console
88+ # - 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
91+
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
96+ }
97+ elseif ($myinv.ScriptName) {
98+ if ($env:TERM_PROGRAM -eq 'vscode') {
99+ # If we are running in vscode, we know the file:line:col links are clickable so we use this format
100+ $posmsg = "${resetcolor}$($myinv.ScriptName):$($myinv.ScriptLineNumber):$($myinv.OffsetInLine)${newline}"
101+ }
102+ else {
103+ $posmsg = "${resetcolor}$($myinv.ScriptName):$($myinv.ScriptLineNumber)${newline}"
104+ }
105+ }
106+ else {
107+ $posmsg = "${newline}"
108+ }
109+
110+ if ($useTargetObject) {
111+ $scriptLineNumber = $_.TargetObject.Line
112+ $scriptLineNumberLength = $_.TargetObject.Line.ToString().Length
113+ }
114+ else {
115+ $scriptLineNumber = $myinv.ScriptLineNumber
116+ $scriptLineNumberLength = $myinv.ScriptLineNumber.ToString().Length
117+ }
118+
119+ if ($scriptLineNumberLength -gt 4) {
120+ $headerWhitespace = ' ' * ($scriptLineNumberLength - 4)
121+ }
122+
123+ $lineWhitespace = ''
124+ if ($scriptLineNumberLength -lt 4) {
125+ $lineWhitespace = ' ' * (4 - $scriptLineNumberLength)
126+ }
127+
128+ $verticalBar = '|'
129+ $posmsg += "${accentColor}${headerWhitespace}Line ${verticalBar}${newline}"
130+
131+ $highlightLine = ''
132+ if ($useTargetObject) {
133+ $line = $_.TargetObject.LineText.Trim()
134+ $offsetLength = 0
135+ $offsetInLine = 0
136+ }
137+ else {
138+ $positionMessage = $myinv.PositionMessage.Split($newline)
139+ $line = $positionMessage[1].Substring(1) # skip the '+' at the start
140+ $highlightLine = $positionMessage[$positionMessage.Count - 1].Substring(1)
141+ $offsetLength = $highlightLine.Trim().Length
142+ $offsetInLine = $highlightLine.IndexOf('~')
143+ }
144+
145+ if (-not $line.EndsWith($newline)) {
146+ $line += $newline
147+ }
148+
149+ # don't color the whole line
150+ if ($offsetLength -lt $line.Length - 1) {
151+ $line = $line.Insert($offsetInLine + $offsetLength, $resetColor).Insert($offsetInLine, $accentColor)
152+ }
153+
154+ $posmsg += "${accentColor}${lineWhitespace}${ScriptLineNumber} ${verticalBar} ${resetcolor}${line}"
155+ $offsetWhitespace = ' ' * $offsetInLine
156+ $prefix = "${accentColor}${headerWhitespace} ${verticalBar} ${errorColor}"
157+ if ($highlightLine -ne '') {
158+ $posMsg += "${prefix}${highlightLine}${newline}"
159+ }
160+ $message = "${prefix}"
161+ }
162+
163+ if (! $err.ErrorDetails -or ! $err.ErrorDetails.Message) {
164+ if ($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception.Message.Contains("~$newline")) {
165+ # need to parse out the relevant part of the pre-rendered positionmessage
166+ $message += $err.Exception.Message.split("~$newline")[1].split("${newline}${newline}")[0]
167+ }
168+ elseif ($err.Exception) {
169+ $message += $err.Exception.Message
170+ }
171+ elseif ($err.Message) {
172+ $message += $err.Message
173+ }
174+ else {
175+ $message += $err.ToString()
176+ }
177+ }
178+ else {
179+ $message += $err.ErrorDetails.Message
180+ }
181+
182+ # if rendering line information, break up the message if it's wider than the console
183+ 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
185+ $prefixVtLength = $prefix.Length - $prefixLength
186+
187+ # replace newlines in message so it lines up correct
188+ $message = $message.Replace($newline, ' ').Replace("`n", ' ').Replace("`t", ' ')
189+
190+ $windowWidth = 120
191+ if ($Host.UI.RawUI -ne $null) {
192+ $windowWidth = $Host.UI.RawUI.WindowSize.Width
193+ }
194+
195+ if ($windowWidth -gt 0 -and ($message.Length - $prefixVTLength) -gt $windowWidth) {
196+ $sb = [Text.StringBuilder]::new()
197+ $substring = Get-TruncatedString -string $message -length ($windowWidth + $prefixVTLength)
198+ $null = $sb.Append($substring)
199+ $remainingMessage = $message.Substring($substring.Length).Trim()
200+ $null = $sb.Append($newline)
201+ while (($remainingMessage.Length + $prefixLength) -gt $windowWidth) {
202+ $subMessage = $prefix + $remainingMessage
203+ $substring = Get-TruncatedString -string $subMessage -length ($windowWidth + $prefixVtLength)
204+
205+ if ($substring.Length - $prefix.Length -gt 0)
206+ {
207+ $null = $sb.Append($substring)
208+ $null = $sb.Append($newline)
209+ $remainingMessage = $remainingMessage.Substring($substring.Length - $prefix.Length).Trim()
210+ }
211+ else
212+ {
213+ break
214+ }
215+ }
216+ $null = $sb.Append($prefix + $remainingMessage.Trim())
217+ $message = $sb.ToString()
218+ }
219+
220+ $message += $newline
221+ }
222+
223+ $posmsg += "${errorColor}" + $message
224+
225+ $reason = 'Error'
226+ if ($err.Exception -and $err.Exception.WasThrownFromThrowStatement) {
227+ $reason = 'Exception'
228+ }
229+ # MyCommand can be the script block, so we don't want to show that so check if it's an actual command
230+ elseif ($myinv.MyCommand -and $myinv.MyCommand.Name -and (Get-Command -Name $myinv.MyCommand -ErrorAction Ignore))
231+ {
232+ $reason = $myinv.MyCommand
233+ }
234+ # 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
237+ }
238+ elseif ($myinv.MyCommand) {
239+ $reason = $myinv.MyCommand
240+ }
241+ elseif ($myinv.InvocationName) {
242+ $reason = $myinv.InvocationName
243+ }
244+ elseif ($err.CategoryInfo.Category) {
245+ $reason = $err.CategoryInfo.Category
246+ }
247+ elseif ($err.CategoryInfo.Reason) {
248+ $reason = $err.CategoryInfo.Reason
249+ }
250+
251+ $errorMsg = 'Error'
252+
253+ "${errorColor}${reason}: ${posmsg}${resetcolor}"
254+ }
255+
256+ $myinv = $_.InvocationInfo
257+ $err = $_
258+ if (!$myinv -and $_.ErrorRecord -and $_.ErrorRecord.InvocationInfo) {
259+ $err = $_.ErrorRecord
260+ $myinv = $err.InvocationInfo
261+ }
262+
263+ if ($err.FullyQualifiedErrorId -eq 'NativeCommandErrorMessage' -or $err.FullyQualifiedErrorId -eq 'NativeCommandError') {
264+ return "${errorColor}$($err.Exception.Message)${resetcolor}"
265+ }
266+
267+ $myinv = $err.InvocationInfo
268+ if ($ErrorView -eq 'DetailedView') {
269+ $message = Get-Error
270+ return "${errorColor}${message}${resetcolor}"
271+ }
272+
273+ if ($ErrorView -eq 'CategoryView') {
274+ $message = $err.CategoryInfo.GetMessage()
275+ return "${errorColor}${message}${resetcolor}"
276+ }
277+
278+ $posmsg = ''
279+ if ($ErrorView -eq 'ConciseView') {
280+ $posmsg = Get-ConciseViewPositionMessage
281+ }
282+ elseif ($myinv -and ($myinv.MyCommand -or ($err.CategoryInfo.Category -ne 'ParserError'))) {
283+ $posmsg = $myinv.PositionMessage
284+ }
285+
286+ if ($posmsg -ne '') {
287+ $posmsg = $newline + $posmsg
288+ }
289+
290+ if ($err.PSMessageDetails) {
291+ $posmsg = ' : ' + $err.PSMessageDetails + $posmsg
292+ }
293+
294+ if ($ErrorView -eq 'ConciseView') {
295+ if ($err.PSMessageDetails) {
296+ $posmsg = "${errorColor}${posmsg}"
297+ }
298+ return $posmsg
299+ }
300+
301+ $indent = 4
302+
303+ $errorCategoryMsg = $err.ErrorCategory_Message
304+
305+ if ($null -ne $errorCategoryMsg)
306+ {
307+ $indentString = '+ CategoryInfo : ' + $err.ErrorCategory_Message
308+ }
309+ else
310+ {
311+ $indentString = '+ CategoryInfo : ' + $err.CategoryInfo
312+ }
313+
314+ $posmsg += $newline + $indentString
315+
316+ $indentString = "+ FullyQualifiedErrorId : " + $err.FullyQualifiedErrorId
317+ $posmsg += $newline + $indentString
318+
319+ $originInfo = $err.OriginInfo
320+
321+ if (($null -ne $originInfo) -and ($null -ne $originInfo.PSComputerName))
322+ {
323+ $indentString = "+ PSComputerName : " + $originInfo.PSComputerName
324+ $posmsg += $newline + $indentString
325+ }
326+
327+ $finalMsg = if ($err.ErrorDetails.Message) {
328+ $err.ErrorDetails.Message + $posmsg
329+ } else {
330+ $err.Exception.Message + $posmsg
331+ }
332+
333+ "${errorColor}${finalMsg}${resetcolor}"
334+
335+ #>
0 commit comments