powershellio-redirectionansi-escapeerror-reporting

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?


Solution

  • There are two independent aspects to consider:


    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:


    [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.