如何在 `c` 中使 win32 控制台识别 ANSI/VT100 转义序列?

92

我正在构建一个轻量级版本的ncurses库。到目前为止,它在VT100兼容终端上运行得非常好,但win32控制台无法识别\033代码作为转义序列的开头:

# include <stdio.h>
# include "term.h"

int main(void) {
  puts(BOLD COLOR(FG, RED) "Bold text" NOT_BOLD " is cool!" CLEAR);
  return 0;
}

Screenshot

C代码层面上需要做什么,才能加载ANSI.SYS驱动程序并识别ANSI/VT100转义序列?


3
请注意,截至最近的Windows 10版本,游戏规则已经发生了巨大变化。 - Andreas Rejbrand
5
FYI,在最新的Windows 10中,您可以通过以下reghack在conhost中启用ANSI -- 在HKCU\Console中创建名为VirtualTerminalLevelDWORD,并将其设置为0x1;然后重新启动cmd.exe。-- 您可以使用以下PowerShell进行测试"?[1;31mele ?[32mct ?[33mroni ?[35mX ?[36mtar ?[m".Replace('?', [char]27); - BrainSlugs83
1
这里是如何在不编辑注册表的情况下启用它,从而避免可能破坏其他应用程序的例子。 - Bogdan Mart
ANSI.SYS是我自从WIN98时代以来就再也没见过的东西。 - Luiz Felipe
显示剩余3条评论
14个回答

84

[更新] 对于最新的 Windows 10,请阅读下面评论中 @brainslugs83 的有用贡献。

而对于 Windows 10 Anniversary Update 之前的版本:

ANSI.SYS 有一个限制,它只能在 Windows 95-Vista 的 MS-DOS 子系统上下文中运行。

Microsoft KB101875 解释了如何在命令窗口中启用 ANSI.SYS,但它不适用于 Windows NT。根据这篇文章:我们都喜欢颜色,现代版本的 Windows 不支持这种好用的 ANSI。

相反,Microsoft 创建了许多函数,但这远远不能满足您操作 ANSI/VT100 转义序列的需求。

有关更详细的说明,请参见维基百科文章

ANSI.SYS 也适用于在 NTVDM 下执行的 16 位遗留程序的 NT 派生系统。

Win32 控制台根本不原生支持 ANSI 转义序列。像 Ansicon 这样的软件可以作为标准 Win32 控制台的包装器,并添加对 ANSI 转义序列的支持。

所以我认为 Jason Hood 的 ANSICON 是您的解决方案。它用 C 语言编写,支持 Windows 的 32 位和 64 位版本,源代码可用

我还发现了一些类似的问题或帖子,最终建议使用 ANSICON:


3
我曾经进行过一项修改以使ANSI在Windows XP上正常运行,无需任何第三方工具。https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/YZnoq80Mcds - est
5
时代变迁啊 ;) 在Windows 10周年更新及以后的版本中,Windows控制台更新了对ANSI/VT序列的相当可靠的支持,并在创作者更新中添加了24位RGB颜色的支持:https://blogs.msdn.microsoft.com/commandline/2016/09/22/24-bit-color-in-the-windows-console - Rich Turner
根据Rich Turner的贡献更新了答案。 - Franco Rondini
1
@Simon 谢谢,我已经删除了链接,因为它无法使用。顺便提一下,这里有一个存档版本的kb/101875 - Franco Rondini
45
FYI,在最新的Windows 10中,您可以通过以下的注册表修改来在conhost中启用ANSI -- 在HKCU\Console中创建一个名为VirtualTerminalLevelDWORD并将其设置为0x1,然后重新启动cmd.exe。-- 您可以使用以下Powershell测试它:"?[1;31mele ?[32mct ?[33mroni ?[35mX ?[36mtar ?[m".Replace('?', [char]27); - BrainSlugs83
1
感谢 @brainslugs83 - 已更新答案并引用了您的评论。 - Franco Rondini

40

5
105xx版本是唯一默认启用VT100序列的版本。在先前和后续版本中,它默认禁用了,因为这是一个错误。请参阅此处的说明:https://wpdev.uservoice.com/forums/266908-command-prompt-console-bash-on-ubuntu-on-window/suggestions/15617610--re-enable-enable-virtual-terminal-processing-by - Anatol Belski
9
请注意,在最新的Windows 10中,您可以通过以下注册表修改来在conhost中启用ANSI --在HKCU\Console中创建一个名为VirtualTerminalLevelDWORD并将其设置为0x1,然后重新启动cmd.exe。-- 您可以使用以下PowerShell进行测试:"?[1;31mele ?[32mct ?[33mroni ?[35mX ?[36mtar ?[m".Replace('?', [char]27); - BrainSlugs83

27

基于@BrainSlugs83的方法,您可以通过注册表在当前的Windows 10版本上激活,具体操作命令如下:

REG ADD HKCU\CONSOLE /f /v VirtualTerminalLevel /t REG_DWORD /d 1

2
这在所有的Windows 10版本中都支持吗?还是只有特定的更新才有? - Youssef13
1
在Windows 10的第一个版本中不受支持,但在当前版本中可以正常工作。 - Daniel De León
我想知道支持这个的具体版本。 - Youssef13
4
根据 https://superuser.com/a/1300251/702169 ,第一个支持的版本是构建16257。 - InQβ

19

对于Python 2.7,在Windows 10(v1607)上,以下脚本对我而言工作正常。

import os

print '\033[35m'+'color-test'+'\033[39m'+" test end"
os.system('') #enable VT100 Escape Sequence for WINDOWS 10 Ver. 1607
print '\033[35m'+'color-test'+'\033[39m'+" test end"

结果应为:

[35mcolor-test[39m test end

color-test test end

1
这开始看起来像黑魔法,之后也没有提到如何关闭控制台设置?奇怪的是,它对我有效,但不清楚为什么从神奇的空字符串开始。 - user337598
1
如果你在括号 (...) 中包裹打印的内容,这在 Windows 10 (v1703) 上的 Python 3 中是有效的。(例如 print('\033[35m'+'color-test'+'\033[39m'+" test end") - whatisit
9
有人有源代码或知道os.system('')会对控制台做出什么改变吗? - Boop
8
os.system('') 看起来是因为 cmd.exe 中的一个bug而能够正常工作的(cmd.exe 开启了 VT 模式,但退出时未将其禁用)。如需更多信息和更好的启用 VT 模式的代码,请参阅 python.org 上的 issue 30075 上的讨论。 - Richard Goulter
你可以通过\033[0m来结束以m结尾的控制台代码。或者,如果你想要重置整个终端并清除屏幕,可以使用\033c - Brōtsyorfuzthrāx

18

13

例如,您可以直接使用“ParseAndPrintString”函数重新编译应用程序。 - Andry

8

3
这个解决方案相当笨重,更不用说它只允许对文本进行着色 - 而不能对ANSI.SYS代码的其他部分进行着色。http://users.cybercity.dk/~bse26236/batutil/help/ANSI~S_S.HTM - Witiko

7

5
也许ANSICON可以帮助您。
只需根据您的Windows操作系统下载并提取文件:32位或64位。
使用以下命令进行安装:ansicon -i

2
我发现这个工具对我的目的很有用。 GitHub上的Microsoft Color Tool 解压缩文件,然后以管理员权限打开CMD。
在CMD中进入你解压缩文件的文件夹。
然后执行这个命令 "colortool -b scheme-name"
scheme-name需要替换为以下任何选项之一:
  • campbell.ini
  • campbell-legacy.ini
  • cmd-legacy.ini
  • deuternopia.itermcolors
  • OneHalfDark.itermcolors
  • OneHalfLight.itermcolors
  • solarized_dark.itermcolors
  • solarized_light.itermcolors
在我的情况下,命令应该是这样的 "colortool -b solarized_dark.itermcolors"。
右键单击控制台窗口,选择“属性”。
您不需要更改任何值,只需单击“确定”以保存设置。(您会注意到您的字体已经包含颜色)。 控制台属性 然后重新启动您的 cmd 或 PowerShell。
ANSI 颜色应该已经启用,并且与您之前选择的配色方案一起工作。

我尝试过这个,但 docker-machine 拒绝连接。 - Ken Ingram
非常抱歉这么久才回复,但是上面的方法从未在Docker中进行过测试。 - Arung Isyadi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接