Skip to content

External application leaks something ANSI-Corrupting into PowerShell session #16741

@jhoneill

Description

@jhoneill

Prerequisites

Steps to reproduce

I can't find this with a search but that may be searching for the wrong thing.

I had a task where the most sensible way to compare two lumps of text was with diff.exe - I'm using the version which is installed with git for convenience - my script worked in the PowerShell Integrated Console in VSCode, but anywhere else I'd see output like this
←[31m Text that should be read ←[0m

That is: an arrow character was printed where there should be an "Escape", and the escape sequence was not processed

by a process of trial and error I established

<<path>>\diff.exe --help ; $y = "`e[31m Red Text `e[0m"; $Y

Would output correctly but

$x =<<path>>\diff.exe --help ; $y = "`e[31m Red Text `e[0m"; $Y

Would render escape as arrow, but $y and it would render correctly in a subsequent command . Output is only corrupted while the command that contains diff.exe is running. The same behaviour occurred with diff.exe <<params>> | pscmdlet or [void](diff.exe <<params>>) anything which stopped the main output going to the console. However git diff commands don't suffer from the error. $x = git diff head~1 ; $x = git diff head~1 ;

I found two workarounds

  1. run Cmd.exe <<path to diff>> <<params>> > tempfile
  2. Use Start-Process -wait -WindowStyle Hidden -RedirectStandardOutput $diffOutput -FilePath $PathToDiff -ArgumentList <<params>>

Note that in the start-process example, If -NoNewWindow is used instead of -WindowStyle Hidden the problem returns

The mechanism of the corruption isn't clear but the something seems to bypassing standard output and impact the console for the duration of that command- whether it is possible for PowerShell to trap it is also not clear.
Nor is it clear how common this problem is: it's possible that diff does something unique, or there may be dozens of cases waiting to be discovered. As more people are coming to pwsh from the Linux world and wanting to bring tools they know, AND use of ansi formatting is getting less niche and more mainstream those cases will emerge - if they are there

Expected behavior

$x =<<path>\diff.exe --help ; $y = "`e[31m Red Text `e[0m"; $Y

Stores the help from diff in $x, and prints "Red Text" in red.

Actual behavior

$x =<<path>\diff.exe --help ; $y = "`e[31m Red Text `e[0m"; $Y

Stores the help from diff in $x, and prints "←[31m Red Text ←[0m" 
However if $y is entered as the next command it prints as a red text. (Commands in the same PS1 file behave like commands joined with ";"  )

Error details

No errors

Environment data

Name                           Value�[0m
----                           -----�[0m
PSVersion                      7.2.1
PSEdition                      Core
GitCommitId                    7.2.1
OS                             Microsoft Windows 10.0.19042
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

image

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions