我写了一个打印字符串的程序,其中包含ANSI escape sequences来使文本着色。但是它在默认的Windows 10控制台中并不像预期的那样工作,就像你在截图中看到的那样。
程序输出显示转义序列作为打印字符。如果我通过变量或管道将该字符串提供给PowerShell,输出将按预期显示(红色文本)。
我怎样才能实现该程序打印彩色文本没有任何变通办法?
这是我的程序源代码(Haskell)--但是语言无关紧要,只是为了让您了解转义序列是如何编写的。
main = do
let red = "\ESC[31m"
let reset = "\ESC[39m"
putStrLn $ red ++ "RED" ++ reset
3条答案
按热度按时间oxcyiej71#
注:
conhost.exe
提供)上的 * 常规 *(传统)控制台窗口,这些窗口 * 默认情况下 * 使用,包括从GUI应用程序启动控制台应用程序时。虽然Windows 10中的控制台窗口原则上 * 确实支持VT(虚拟终端)/ ANSI转义序列,但默认情况下关闭**支持。
您有三个选项:
[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
SetConsoleMode()
Windows API函数,从程序内部激活支持 ,仅针对该程序(进程)。Out-Host
;例如,.\test.exe | Out-Host
回复(a):
基于注册表的方法总是 * 全局地 * 激活VT支持,即对于 * 所有 * 控制台窗口,而不管在其中运行什么 shell /程序:
注:
[HKEY_CURRENT_USR\Console]
的 subkeys 由启动可执行文件/窗口标题限定范围,但VirtualTerminalLevel
值似乎在那里不受支持。*.lnk
)(例如从开始菜单或任务栏)打开控制台窗口不会遵守这些设置,因为*.lnk
文件 * 内置了设置 *;虽然您可以通过Properties
GUI对话框修改这些内置设置,但在撰写本文时,VirtualTerminalLevel
设置尚未出现在该GUI中。回复(B):
从程序(进程)* 内部调用
SetConsoleMode()
Windows API函数 *(如下所示),即使在C#中也很麻烦(因为需要P/Invoke声明),而且可能不是选项:在这种情况下,下面讨论的选项(c)(来自PowerShell)可能对您有用。
回复(c):
PowerShell在启动时*会自动为自身激活VT(虚拟终端)支持(在Windows 10的最新版本中,这同时适用于Windows PowerShell和PowerShell(Core)7+),但不会 * 扩展到从 * Windows PowerShell调用的外部程序。但从PowerShell(Core)调用时,*会 * 扩展到至少从7.2起的版本。
$PSStyle.OutputRendering
* 首选项变量***,它**控制 PowerShell 命令是否通过formatting system**生成彩色输出, 例如Get-ChildItem
输出的彩色标题。从 * 外部程序 * 的(直接)输出。$PSStyle.OutputRendering
默认为Host
,这意味着只有打印到终端(控制台)的格式化输出是彩色的。$PSStyle.OutputRendering = 'PlainText'
禁用彩色,$PSStyle.OutputRendering = 'Ansi'
使其无条件;有关详细信息,请参见this answer。但是,作为Windows PowerShell的变通方案,您可以通过PowerShell命令中继 * 外部程序的输出,在这种情况下,* VT序列 * 被 * 识别**;使用
Out-Host
是最简单的方法(Write-Host
也可以):注:仅当您打算打印到 * 控制台 * 时才使用
Out-Host
;相反,如果您想 * 捕获 * 外部程序的输出,则只使用$capturedOutput = .\test.exe
或者,您可以**将调用封装在
(...)
*中,但是,在中继之前, 总是先收集所有输出 *。字符编码警告:默认情况下,Windows PowerShell希望外部程序的输出使用OEM代码页,如旧系统区域设置所定义(例如,美国-英语系统上的
437
)和[console]::OutputEncoding
中所反映的。.NET控制台程序会自动遵守该设置,但非.NET程序除外(例如Python脚本)使用不同的编码(并且不只是生成纯ASCII输出(在7位范围内)),则必须(至少暂时)通过赋值[console]::OutputEncoding
来指定该编码;例如,对于UTF-8:[console]::OutputEncoding = [Text.Encoding]::Utf8
.请注意,这不仅是VT序列解决方案所必需的,而且通常是PowerShell正确解释非ASCII字符所必需的。
PowerShell Core(v6+),不幸的是,从v7.3开始,仍然默认为OEM代码页,但是should be considered a bug,因为它默认为 UTF-8,没有BOM。
epfja78i2#
感谢用户mklement0让我意识到VT支持不是自动启用的,这让我看向了正确的方向,我找到了this helpful post。
所以要回答我的问题:添加或设置注册表项
重新启动控制台,它就能工作了。
pw136qt23#
特别是对于Haskell,您需要调用hSupportsANSIWithoutEmulation函数以在Windows 10上的程序中启用ANSI转义序列。