Skip to content

Stop writing DECCKM sequences when reading commands from stdin - #28185

Open
candygoogy (candygoogy) wants to merge 2 commits into
PowerShell:masterfrom
candygoogy:fix-stdin-vt-sequences
Open

candygoogy (candygoogy) wants to merge 2 commits into
PowerShell:masterfrom
candygoogy:fix-stdin-vt-sequences

Conversation

@candygoogy

Copy link
Copy Markdown

PR Summary

When pwsh reads its commands from stdin (pwsh -c -, pwsh -Command -, pwsh -File -, or plain
pwsh with redirected input) on Linux or macOS, it no longer writes the ESC[?1h / ESC[?1l
(DECCKM) sequences into the output.

The console host turns DECCKM on before reading each line and off before running it, so .NET gets
VT input for the cursor keys (added in #14943). That only matters when a person is typing at a
terminal. When commands come from stdin, the input is read as plain lines and the cursor keys are
never used, so these writes ended up in the output, for example in a file when stdout is redirected.

The change adds !ui.ReadFromStdin to the two checks in the prompt loop in ConsoleHost.cs. The
exit path already skips DECCKM in this case, because it checks IsInteractive, which is false
when reading from stdin. The interactive behavior from #14943 doesn't change. The code is inside
#if UNIX, so Windows was never affected.

PR Context

Fix #26631

The Engine WG agreed that the host should not write these VT sequences when it processes stdin as
commands.

Before (Linux, printf 'echo hi\necho there\n' | pwsh -NoProfile -c - > out.txt):

1b 5b 3f 31 68 1b 5b 3f 31 6c 68 69 0a 1b 5b 3f  .[?1h.[?1lhi..[?
31 68 1b 5b 3f 31 6c 74 68 65 72 65 0a 1b 5b 3f  1h.[?1lthere..[?
31 68                                            1h

After:

68 69 0a 74 68 65 72 65 0a                       hi.there.

Testing:

  • New test in test/powershell/Host/ConsoleHost.Tests.ps1: it runs pwsh with commands on stdin and
    redirected output (-c -, -Command -, -File - and no arguments) and checks that the output
    has no ESC character. The test removes NO_COLOR and sets TERM, because NO_COLOR makes the
    host strip these sequences. This is why the existing redirected-stdin tests (which set NO_COLOR)
    didn't catch the bug.
  • On Linux (Debian 12 x64), the new test fails without the fix (all 4 cases) and passes with it.
    The existing "Redirected standard input for 'interactive' use" tests pass with and without the fix.
    I didn't run the rest of ConsoleHost.Tests.ps1 on Linux.
  • On Windows the new test passes with and without the fix (the code is Unix-only), and
    ConsoleHost.Tests.ps1 gives the same results with and without the fix.

PR Checklist

On Unix, the prompt loop turns DECCKM on before reading a line and off
before running it, so that .NET gets VT input for the cursor keys. When
the commands come from stdin (-Command -, -File -, or redirected input),
the lines are read from stdin and the cursor keys are never used, so the
sequences only ended up in the output, for example in a redirected file.

Skip both writes when reading from stdin, as the exit path already does.
@candygoogy
candygoogy (candygoogy) requested a review from a team as a code owner October 11, 2026 15:47
Copilot AI balanced review requested due to automatic review settings October 11, 2026 15:47
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new test parameter violates the repository’s PowerShell parameter-naming convention.

1 open finding
What changed in this PR

Prevents Unix console hosts from emitting DECCKM sequences when commands are read from redirected stdin.

Changes:

  • Gates DECCKM toggling on ReadFromStdin.
  • Adds Pester coverage for four stdin invocation forms.
File Description
ConsoleHost.cs Suppresses DECCKM for redirected stdin.
ConsoleHost.Tests.ps1 Tests redirected-stdin output for escape characters.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +664 to +671
It "Does not write VT sequences to the output: <Arguments>" -TestCases @(
@{Arguments = "-noprofile -c -"}
@{Arguments = "-noprofile -Command -"}
@{Arguments = "-noprofile -File -"}
@{Arguments = "-noprofile"}
) {
param($Arguments)
$si = NewProcessStartInfo $Arguments -RedirectStdIn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Write-Host prints ANSI control characters when running script from stdin even if stdout is redirected

2 participants