我编写了一个程序,该程序打印一个字符串,其中包含ANSI escape sequences,以使文本变色。但是,如屏幕截图所示,它在默认的Windows 10控制台中无法正常工作。
程序输出与转义序列一起显示为打印字符。 如果我通过变量或管道将该字符串提供给PowerShell,则输出将按预期显示(红色文本)。
如何实现程序打印彩色文本而没有任何解决方法?
这是我的程序源(Haskell)-但是语言无关,只是为了您可以了解转义序列的编写方式。
main = do
let red = "\ESC[31m"
let reset = "\ESC[39m"
putStrLn $ red ++ "RED" ++ reset
答案 0 :(得分:23)
虽然Windows 10中的控制台窗口确实支持VT(虚拟终端)/ ANSI转义序列 原则上,但默认情况下关闭了支持< / em> 。
您有三个选择:
(a)默认情况下,通过注册表全局永久地 激活支持,如this SU answer中所述。
[HKEY_CURRENT_USER\Console]
中,将VirtualTerminalLevel
DWORD值创建或设置为1
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
基于注册表的方法始终在全局范围内激活 的VT支持,即对于 all 控制台窗口,无论在什么shell /程序中运行他们:
如果需要,单个可执行文件/ shell仍可以使用方法(b)取消对自身的支持。
这意味着,任何未明确控制VT支持的程序的输出都将受VT序列的解释;尽管通常这是理想的,但是假设这可能会导致对偶然产生具有VT样序列的输出的程序的输出产生误解。
注意:
是一种机制,它允许控制台窗口设置通过[HKEY_CURRENT_USR\Console]
的子键由启动可执行文件/窗口标题来确定范围, VirtualTerminalLevel
值似乎不被支持。
尽管如此,但这也不是一个健壮解决方案,因为它是通过 shortcut 文件({{1} })(例如从“开始”菜单或任务栏)将不遵守这些设置,因为*.lnk
文件具有内置设置;虽然您可以通过*.lnk
GUI对话框修改这些内置设置,但截至本文撰写之时,Properties
设置尚未显示在该GUI中。
如here所述,从程序(进程)内部调用VirtualTerminalLevel
Windows API函数 即使在C#中也很麻烦(由于需要P / Invoke声明),并且可能不是一个选项:
用于使用不支持调用Windows API的语言编写的程序。
,如果您已有一个无法修改的可执行文件。
如果您不想在这种情况下全局启用支持(选项(a)),则选项(c)(来自PowerShell)可能对您有用。
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 转义序列。