Is it possible to stop `powershell` wrapping output in ANSI sequences?
Asked Answered
A

2

5

I CreateProcess(win32) powershell and read raw bytes from it. And I see that it produces a lot of invisible chars. For example \u{1b}[2J\u{1b}[m\u{1b}[

Is there any way how to stop it?

*Exactly it's possible to strip them manually but I do hope there other way.

Aeromarine answered 5/9, 2021 at 13:3 Comment(0)
U
14
  • You mention powershell (powershell.exe), i.e. the CLI of Windows PowerShell.

  • Windows PowerShell (unlike PowerShell (Core) 7+, see below) itself does not use coloring / formatting based on VT / ANSI escape sequences.

  • The implication is that third-party code is producing the VT sequences in your case, so you must deactivate (or reconfigure) it to avoid such sequences in the output.

    • A prime candidate is a custom prompt function; such functions often involve coloring for a better command-line experience.

    • In programmatic use of powershell.exe, however, you would only see what the prompt function prints if you feed PowerShell commands to the CLI's stdin, accompanied by passing argument -File - to the CLI (to instruct it to read commands from stdin) or by default.

    • To exclude the prompt-function output from the output altogether, use -Command -, as discussed in the answer to your previous question.

    • If you do want it, but want to use the default prompt string, suppress $PROFILE loading with the -NoProfile parameter, which is generally preferable in programmatic processing.


Controlling use of colored output (VT / ANSI escape sequences) in PowerShell (Core) 7.2+

In PowerShell (Core) 7+ (pwsh.exe) - but not in Windows PowerShell (powershell.exe) - PowerShell itself situationally uses VT (ANSI) escape sequence to produce formatted/colored output, such as in the output of Select-String and, in v7.2+, in formatted output in general, notably column headers in tabular output / property names in list output.

  • In PowerShell 7.2+ you can categorically suppress these as follows:

    • Note: Categorically disabling VT (ANSI) sequences is generally not necessary, because PowerShell automatically suppresses them when output is not sent to the host (display); that is, $PSStyle.OutputRendering defaults to Host[1].

      • This amounts to the same behavior that many Unix utilities (sensibly) exhibit: coloring is by default only applied when printing to the display (terminal), not when piping to another command or redirecting to a file.
      • However, note that $PSStyle.OutputRendering only applies to objects that are formatted by PowerShell's for-display formatting system and only when such formatted representations are converted to string data, either explicitly with Out-String, or implicitly with > / Out-File or when piping to an external program.[2]
    • From outside PowerShell, before launching it:

      • By defining the NO_COLOR environment variable, with any value, such as 1.

        • This causes PowerShell to set $PSStyle.OutputRendering to PlainText on startup, which instructs PowerShell not to use VT / ANSI escape sequences.

        • A growing number of external programs also respect this env. variable - see no-color.org

      • Alternatively, by setting the TERM environment variable to xtermm / xterm-mono (also sets $PSStyle.OutputRendering to 'plaintext'):

        • Note that value dumb, at least as of PowerShell Core 7.3.3, doesn't work: while it does cause $host.UI.SupportsVirtualTerminal to then reflect $false, as documented, $PSStyle.OutputRendering remains at its default, Host, and actual formatted output (such as from Get-Item /) still uses colors.
        • However, setting TERM may be more effective than NO_COLOR in getting external programs not to emit VT sequences - ultimately, there's no guarantee however.
        • That said, modifying TERM, especially setting it to value dumb, is best avoided in general, because external programs (on Unix-like platforms) may rely on the TERM variable for inferring (also non-color-related) capabilities of the hosting terminal application (which setting the variable to dumb takes away altogether and - at least hypothetically - value xtermm / xterm-mono may misrepresent the true fundamental terminal type).
    • From inside PowerShell:

      • Set $PSStyle.OutputRendering = 'PlainText'.

        • Note that this alone - unlike the environment variables discussed above - does not affect the behavior of external programs.

        • However, if $PSStyle.OutputRendering = 'PlainText' is in effect, you can suppress rendering of the ANSI escape sequences in the stdout output from external programs, simply by piping to Out-Host or even Out-String, or, with collect-all-output-first behavior, by enclosing an external-program call in (...); notably, this does not remove the escape sequences from the actual data (PowerShell 7.2.x used to do that with Out-String and Out-File, but the behavior was changed in v7.3+ - see GitHub issue #17509).

Note that third-party PowerShell code that uses VT sequences, especially if it predates PowerShell (Core) 7+, may not respect any of the standard mechanisms described above for disabling them (though may conceivably offer a custom mechanism).


[1] This applies since v7.2.0-preview.9, where Host was made the default and the previous default, Automatic, was removed altogether. In preview versions of v7.3.0, Ansi was temporarily the default, but since the official v7.3.0 release the (sensible) default is again Host.

[2] Notably, this means that string data that has embedded ANSI / VT escape sequences is not subject to $PSStyle.OutputRendering in v7.3+ (a change from v7.2), because strings aren't handled by the formatting system (they print as-is).

Unbelief answered 5/9, 2021 at 17:52 Comment(0)
A
3

You can disable ANSI output rendering by setting the environment variable TERM to dumb:

SetEnvironmentVariable(TEXT("TERM"), TEXT("dumb"));
// proceed with your call to CreateProcess
Abattoir answered 5/9, 2021 at 13:42 Comment(3)
I guess it's what I am looking for. SetEnvironmentVariable though doesn't work like your described. ``` SetEnvironmentVariable: The term 'SetEnvironmentVariable' is not recognized as a name of a cmdlet, function, script file, or executable program. ``` I do it like this [System.Environment]::SetEnvironmentVariable("TERM", "dumb") But not all sequences are striped ultimately (if any) :(. Invisible chars are present before endline and after ``` \u{1b}[9X\r\n\u{1b}[31X\r\nEXPECTED_PROMPT> Ping statistics for 8.8.8.8:\u{1b}[28X\r\n ```Aeromarine
+1 for the general pointers, though I don't think they apply here; even when they do apply (PowerShell (Core) 7.2+ and its preview versions), the answer is: it's complicated.Unbelief
This worked for me to stop colored output in Windows PowerShell. thanks.Richter

© 2022 - 2025 — McMap. All rights reserved.