在PowerShell控制台中使用ANSI / VT100代码输出彩色文本

时间:2018-08-03 22:19:35

标签: powershell ansi windows-console vt100

我编写了一个程序,该程序打印一个字符串,其中包含ANSI escape sequences,以使文本变色。但是,如屏幕截图所示,它在默认的Windows 10控制台中无法正常工作。

程序输出与转义序列一起显示为打印字符。 如果我通过变量或管道将该字符串提供给PowerShell,则输出将按预期显示(红色文本)。

如何实现程序打印彩色文本而没有任何解决方法?

enter image description here

这是我的程序源(Haskell)-但是语言无关,只是为了您可以了解转义序列的编写方式。

main = do
    let red = "\ESC[31m"
    let reset = "\ESC[39m"
    putStrLn $ red ++ "RED" ++ reset

3 个答案:

答案 0 :(得分:23)

虽然Windows 10中的控制台窗口确实支持VT(虚拟终端)/ ANSI转义序列 原则上,但默认情况下关闭了支持< / em>

您有三个选择:

  • (a)默认情况下,通过注册表全局永久地 激活支持,如this SU answer中所述。

    • 简而言之:在注册表项[HKEY_CURRENT_USER\Console]中,将VirtualTerminalLevel DWORD值创建或设置为1
      • 在PowerShell中,您可以通过编程方式 进行以下操作:
        Set-ItemProperty HKCU:\Console VirtualTerminalLevel -Type DWORD 1
      • 来自cmd.exe(也可用于PowerShell):
        reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1
    • 打开一个新的控制台窗口,使更改生效。
    • 请参阅以下注意事项。
  • (b)通过调用SetConsoleMode() Windows API从程序内部为该程序(进程)激活支持 功能。

    • 请参阅下面的详细信息。
  • (c)临时解决方法,来自PowerShell :将外部程序的输出通过管道传递到Out-Host;例如.\test.exe | Out-Host

    • 请参阅下面的详细信息。

Re(a):

基于注册表的方法始终在全局范围内激活 的VT支持,即对于 all 控制台窗口,无论在什么shell /程序中运行他们:

  • 如果需要,单个可执行文件/ shell仍可以使用方法(b)取消对自身的支持。

  • 相反,
  • 这意味着,任何未明确控制VT支持的程序的输出都将受VT序列的解释;尽管通常这是理想的,但是假设这可能会导致对偶然产生具有VT样序列的输出的程序的输出产生误解。

注意:

  • 是一种机制,它允许控制台窗口设置通过[HKEY_CURRENT_USR\Console]子键由启动可执行文件/窗口标题来确定范围, VirtualTerminalLevel值似乎不被支持。

  • 尽管如此,但这也不是一个健壮解决方案,因为它是通过 shortcut 文件({{1} })(例如从“开始”菜单或任务栏)将不遵守这些设置,因为*.lnk文件具有内置设置;虽然您可以通过*.lnk GUI对话框修改这些内置设置,但截至本文撰写之时,Properties设置尚未显示在该GUI中。


Re(b):

here所述,从程序(进程)内部调用VirtualTerminalLevel Windows API函数 即使在C#中也很麻烦(由于需要P / Invoke声明),并且可能不是一个选项

  • 用于使用不支持调用Windows API的语言编写的程序。

  • ,如果您已有一个无法修改的可执行文件。

如果您不想在这种情况下全局启用支持(选项(a)),则选项(c)(来自PowerShell)可能对您有用。


Re(c):

PowerShell启动时会自动自动激活VT(虚拟终端)支持 (在Windows 10的最新版本中,这同时适用于Windows PowerShell和PowerShell Core)。

因此,如果您通过PowerShell 中继外部程序的输出,则可以识别VT序列 ;使用Out-Host是最简单的方法(SetConsoleMode()也可以):

Write-Host

注意:仅当您打算打印到控制台时,才使用.\t.exe | Out-Host ;相反,如果您要捕获外部程序的输出,则仅使用Out-Host

字符编码警告:默认情况下,Windows PowerShell期望外部程序的输出使用OEM代码页,如旧系统语言环境所定义(例如,美国英语中的$capturedOutput = .\test.exe系统),并反映在437中。 .NET控制台程序自动遵守该设置,但是对于使用不同编码(并且不仅产生纯ASCII输出(在7位范围内)的非.NET程序(例如Python脚本)),您必须(至少临时)通过分配给[console]::OutputEncoding来指定编码;例如,对于UTF-8:
[console]::OutputEncoding
请注意,这不仅对于VT序列解决方法而言是必需的,而且对于PowerShell正确地呈现非ASCII字符通常也是必需的

不幸的是,

PowerShell Core 截至v6.1.0-preview.4仍仍默认为OEM代码页,但默认为should be considered a bug,因为PowerShell Core否则默认为< em>没有BOM的UTF-8

答案 1 :(得分:5)

感谢用户mklement0使我知道VT支持没有自动启用。这使我朝正确的方向看,并且发现了this helpful post

所以回答我的问题:添加或设置注册表项

HKCU:\Console  -  [DWORD] VirtualTerminalLevel = 1

重新启动控制台,它可以正常工作。

答案 2 :(得分:0)

特别是对于 Haskell,您需要调用 hSupportsANSIWithoutEmulation 函数以在 Windows 10 上的程序中启用 ANSI 转义序列。