Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure PowerShell 7 to output error messages without formatting?

I switched from PowerShell 5.1 to the latest PowerShell 7.5.1 and noticed that the errors that my scripts produce are formatted differently. This runs on Windows Server 2019 Standard [Version 10.0.17763.7136].

I'm running my PowerShell scripts by having this line in the CMD script:

With PowerShell 5:

powershell -command "& 'c:\binaries\scripts\ServiceNow.ps1'" >> my.log

With PowerShell 7:

pwsh.exe -command "& 'c:\binaries\scripts\ServiceNow.ps1'" >> my.log

This is an example of an error that I see in the log file from PowerShell 5:

Export-Csv : Cannot validate argument on parameter 'Encoding'. The argument "utf8NoBOM" does not belong to the set 
"Unicode,UTF7,UTF8,ASCII,UTF32,BigEndianUnicode,Default,OEM" specified by the ValidateSet attribute. Supply an 
argument that is in the set and then try the command again.
At C:\binaries\scripts\ServiceNow.ps1:64 char:75
+ ...  | Export-Csv -Path $strSitesFileNameMain -Encoding utf8NoBOM -NoType ...
+                                                         ~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.ExportCsvCommand
 

And this is an example of error message that I get from PowerShell 7:

[31;1mMethodInvocationException: [0mC:\binaries\scripts\ServiceNow.ps1:141[0m
[31;1m[0m[36;1mLine |[0m
[31;1m[0m[36;1m[36;1m 141 | [0m     [36;1m$webclient.UploadFile($uri, $item.FullName)[0m
[31;1m[0m[36;1m[36;1m[0m[36;1m[0m[36;1m     | [31;1m     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[0m
[31;1m[0m[36;1m[36;1m[0m[36;1m[0m[36;1m[31;1m[31;1m[36;1m     | [31;1mException calling "UploadFile" with "2" argument(s): "The remote name could not be resolved"[0m

That weird character before [31; has ASCII code 0x1B (27). Plus all these extra [36;1m noise. I suspect that these are the codes to format the message in different colours when it is shown in the console, but in my case this output is simply redirected into a plain text log file using >> my.log in the CMD script.

As you can see messages from PS5 are much more readable than from PS7.

How do I return back to that old message style?

like image 589
Vladimir Baranov Avatar asked Nov 17 '25 07:11

Vladimir Baranov


1 Answers

There are two independent aspects to consider:

  • In Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1), the default error formatting, as reflected in and determined by the $ErrorView preference variable, is 'NormalView', whereas in PowerShell (Core) 7, it is (the newly introduced) 'ConciseView'.

    • 'ConciseView' is generally less noisy than NormalView while typically still being descriptive enough, but if you prefer the latter, you'll need to execute $ErrorView = 'NormalView' in PowerShell (Core) 7[1] - this aspect is not covered in the solution below.
  • PowerShell (Core) 7 - unlike Windows PowerShell - uses Virtual Terminal (VT) aka ANSI escape sequences embedded in its error messages to achieve coloring - these are the "weird characters" you're seeing (if you were to print the file content to a console (terminal), you'd see the coloring).

    • This coloring can be suppressed by setting $PSStyle.OutputRendering = 'PlainText' in-session or by setting environment variable NO_COLOR to a value such as 1 before invoking PowerShell - see the about_ANSI_Terminals help topic.

Thus, to suppress the use of VT sequences from cmd.exe / a batch file:

set NO_COLOR=1
pwsh.exe -File c:\binaries\scripts\ServiceNow.ps1 >> my.log

Note:

  • -File rather than -Command is used above, which obviates the need to use &, the call operator, as well as any embedded quoting. For guidance on when to use -File vs. -Command, see this answer.

  • $PSStyle.OutputRendering defaults to 'Host', which indicates that VT sequences are only to be used when printing output to the host (console), as apposed to output being captured in a variable, sent through the pipeline to another command, or redirected to a file.

    • While this logic applies in-session, it inexplicably does not apply to calls to pwsh, the PowerShell (Core) 7 CLI: the fact that the CLI output is being redirected to a file (>> my.log) is not detected - hence the need for set NO_COLOR=1.

    • This problematic inconsistency is the subject of GitHub issue #20170.


[1] In a nutshell, ConciseView prints a single-line error description of the form <source>: <description>, e.g. Get-Item: Cannot find path 'c:\tmp\NoSuch' because it does not exist., whereas NormalView prints a multiline description that includes metadata about the error, e.g., Get-Item : Cannot find path 'C:\tmp\NoSuch' because it does not exist. <newline>At C:\tmp\demo.ps1:5 char:1 <newline>+ Get-Item NoSuch <newline>+ ~~~~~~~~~~~~~~~ <newline> + CategoryInfo : ObjectNotFound: (C:\tmp\NoSuch:String) [Get-Item], ItemNotFoundException <newline> + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
However, note that even in 'ConciseView' errors are situationally multiline, namely if they are reported during execution of a script file (*.ps1) - as opposed to errors reported from a function or cmdlet invoked from outside a script file, such as interactively. Errors reported from a script file are preceded by four lines containing location information, i.e. the path of the script file, the number and text of the line containing the error-triggering statement, similar to the first four lines shown for 'NormalView' above, except for the error description, which follows the location information in 'ConciseView'.
More detailed error information can always be obtained later in PowerShell 7, via the Get-Error cmdlet; in Windows PowerShell, you can use something like $Error[0] | Format-List -Force.

like image 132
mklement0 Avatar answered Nov 20 '25 05:11

mklement0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!