摘要:win10的cmd对颜色的显示不太友好,在捯饬的过程中差点把电脑搞崩。
文章说明
文章作者:鴻塵
参考资料:
- 解决CMD命令行窗口不显示颜色问题python
- cmd命令提示符文本颜色输出
- Github ANSICON
- CMD窗口无法显示带颜色文字输出
- 特殊命令之REG命令
- 转义序列Escape Sequences及Linux echo命令多种颜色显示
- Linux终端和win32控制台文本颜色输出
- 控制台输出颜色控制(Console 模式下的颜色显示)
- 命令行里输出带颜色的字体
- Windows cmd(DOS)命令窗口中echo命令ANSI转义显示彩色字或背景
文章链接:Windows命令行中正确显示颜色
1.背景
为了搞好这个问题,差点把电脑给搞崩了,在这里特意记录下来,算是留给自己的一个教训。
临近毕业,这两天什么事情都没有,就等着参加毕业典礼然后跑路。就想着写点东西吧,hexo部署的时候无法正常显示颜色。如图(注意最后一行):
其实呢,这个问题早就出现了,见Hexo博客搭建(1)——建站及部署之部署Hexo,只不过一直没管它,现在闲下来了就想拯救一下处女座强迫症。
不仅如此,cmd中只能识别^[[35m 文字 ^[[0m
而不能识别\33[35m 文字 \33[0m
,也就是说无法正确转义\033
。
需要注意的是,^[
是一个字符,且只能在命令行下通过组合键Ctrl + [
输入(还有其他方式输入,见后文)。
鉴于以上问题,在经过较长时间的折腾后,找到了一个可用的方法:ANSICON。
2.解决方案
2.1.colorama
在Python中显示颜色主要参考「解决CMD命令行窗口不显示颜色问题python」,用到的库为colorama
,代码如下:1
2
3
4from colorama import init
init(autoreset=True)
print("\033[35m 紫色 \033[0m") #紫色
上述方法通过颜色代码实现颜色的显示,也可以使用Fore
设置颜色:1
2
3
4
5
6from colorama import init, Fore
init(autoreset=True)
print(Fore.YELLOW + "黄色")
print("普通文字")
print(Fore.MAGENTA + "洋红色")colorama
方法只适用于python程序在终端上打印彩色文字,并不能解决其他程序的输出。
2.2.ANSICON
鉴于上述问题,在查找了海量资料后,参考「cmd命令提示符文本颜色输出」,最终找到了ANSICON。
ANSICON基本上可以完美解决遇到的关于cmd颜色的所有问题,这是它的自我介绍:
ANSICON provides ANSI escape sequences for Windows console programs. It provides much the same functionality as
ANSI.SYS
does for MS-DOS.
在64位Windows上,ANSICON包含了主程序ansicon.exe
和扩展ANSI64.dll
,在cmd中运行该程序即可开启一个子shell,在子shell中即可正常显示颜色,不会出现图一的问题。
ANSICON帮助信息如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26ANSICON by Jason Hood <jadoxa@yahoo.com.au>.
Version 1.89 (29 April, 2019). Freeware.
http://ansicon.adoxa.vze.com/
Process ANSI escape sequences in Windows console programs.
ansicon [-lLEVEL] [-i] [-I] [-u] [-U] [-m[ATTR]] [-p[u]]
[-e|E STRING | -t|T [FILE...] | PROGRAM [ARGS]]
-l set the logging level (1=process, 2=module, 3=function,
+4=output, +8=append, +16=imports, +32=files) for PROGRAM
-i install - add ANSICON to CMD's AutoRun entry (also implies -p)
-u uninstall - remove ANSICON from the AutoRun entry
-I -U use local machine instead of current user
-m use grey on black ("monochrome") or ATTR as default color
-p hook into the parent process
-pu unhook from the parent process
-e echo STRING
-E echo STRING, don't append newline
-t display files ("-" for stdin), combined as a single stream
-T display files, name first, blank line before and after
PROGRAM run the specified program
nothing run a new command processor, or display stdin if redirected
ATTR is one or two hexadecimal digits; please use "COLOR /?" for details.
It may start with '-' to reverse foreground and background (but not for -p).
由上可知,直接运行该程序将不带任何参数,开启一个新的命令行进程,这也是后来悲催的直接原因。现在看来,貌似只需要加上-i
选项将其添加到cmd的AutoRun
即可。
3.采坑之路
3.1.问题产生
到目前为止,好像一切正常,文章开始说的「差点把电脑搞崩」又是怎么回事呢?
因为担心会出现其他问题,所以并没有安装ANSICON,开启子shell好像也没有什么问题,无非就是每次都要手动输入命令/path/to/ansicon.exe
。这也不是什么问题,只要把ansicon.exe
文件路径加入到环境变量中即可。
为了省事我直接把ansicon.exe
和ANSI64.dll
复制到C:/Windows/System32/
目录下,这样一来在任何命令行下都可以直接运行ansicon
命令了。
当需要正常显示颜色时,输入ansicon
即可,如图所示:
上图中,直接打印颜色将显示乱码,在ansicon的子shell中则可以正常显示,输入exit
才可退出shell。此时再打印颜色仍会乱码,因为只有在ansicon的shell中才可以正常显示。
在查资料的时候,偶然看到了一篇文章:CMD窗口无法显示带颜色文字输出。文章中提到,利用注册表的AutoRun
字符串值可以实现在打开CMD窗口时自动执行命令。于是,我就设想修改注册表,在每次打开CMD的时候让他自动执行ansicon
命令,那么就不需要手动输入了。
说干就干,Win + R
打开运行,输入regedit
打开注册表编辑器,定位到计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor
下,新建字符串值AutoRun
,双击该值,在数值数据中填写ansicon
,一气呵成。
此时我已经迫不及待地要测试了,然而,当我打开cmd的时候,窗口中却疯狂打印Microsoft Windows [版本 10.0.18363.1556](c) 2019 Microsoft Corporation。保留所有权利。
,此时我已经感觉不妙。好在它只开了一个窗口(注意,这是一个伏笔……),我不得不一直按Ctrl + C
让它停下来,甚至直接叉掉这个窗口。
我又查了半天,一直都以为是注册表修改方式不对,又不知道在哪里看到了cmd /k xxx
这样的一个命令,就是这个命令让我的电脑直接崩溃。该命令会打开一个新窗口来执行xxx
命令。于是抱着试一试的心态我把上面注册表的数值数据改成了cmd /k ansicon
,当我打开CMD窗口的一瞬间,电脑内存急剧增加,无限开启新窗口并执行ansicon
命令。
自此走上了修电脑的艰难之路。
3.2.艰难解决
由于电脑内存卡爆,无法进行任何操作,就算想删除注册表值也没办法,因为鼠标键盘根本动不了。无奈之下,准备重启电脑,跟它抢速度,在内存爆满之前把注册表改回来。事实证明我还是太天真了,电脑一开机他就开始了,根本不给时间你去做其他操作,如图:
到这里已经没有任何办法了,系统还原也不行,因为我很早就删除了系统还原点(只为节省那么一丢丢内存…),现在只能重装系统了,甚至连U盘启动盘都做好了。重装系统倒是无所谓,但是电脑里有很多重要的文件、配置、安装的软件等。我真的不想重装系统,但是没办法啊!
上图是准备重装系统之前拍的照,为的是留一个桌面布局,可以看到右侧命令行窗口边缘厚厚的一层黑边,都不知道开了多少个窗口了。
从U盘重装系统还要设置一下BIOS,开启UEFI什么的。然而哪有那么顺利,就在我失败了无数次一心想要操作系统的时候,他却提示各种错误,要么是某个地方设置不对、要么是某个选项没有开启。在反复的重启和设置中,突然发现了一个修复的选项。在这种连系统都不让我重装的情况下,无疑给了我一丝希望。
然而,新的问题又出现了,所有的修复选项都试过了还是没用,这让我整个人都不好了,一度濒临崩溃。
世事总是这样,在你最绝望的时候才会显现一丝曙光。
在某一个修复选项中,可以打开命令行窗口,目测盘符X
应该是U盘吧,Source
目录就是启动盘的位置。如图所示:
但是一个命令行能干什么呢?这里的命令行是有管理员权限的,最直接的想法就是在这里删除注册表值,然后重启就完美了。
搜了一下,发现还真有操作注册表的命令REG
,还有对应的QUREY
、ADD
、DELETE
等选项,此处参考了特殊命令之REG命令。这令我大喜过望,感觉胜利就在眼前。然而,当我查询HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor
下的值时,却没有AutoRun
这一项(如上图),只有如下几项:1
2
3
4CompletionChar REG_DWORD 0x9
DefaultColor REG_DWORD 0x0
EnableExtensions REG_DWORD 0x1
PathCompletionChar REG_DWORD 0x9
通过对比3.1节《问题产生》的图二和上图,唯独少了AutoRun
这一项。这另外百思不得其解的同时,也是十分郁闷。我测试过REG ADD
和REG DELETE
,好像都成功了,为何这里就查询不到呢?看来这个方法又行不通了。
就在我一筹莫展的时候,突然灵机一动,产生问题的根本原因在于无限启动新窗口从而运行ansicon
命令,那我可以人为破坏掉他的运行环境啊。
于是我在命令行里试着删除文件C:\Windows\System32\ANSI64.dll
,结果成功了。
赶紧重启电脑,尽管仍然会无限开启新窗口,但果然没那么卡了,因为ansicon
命令无法正常运行。于是可以打开注册表编辑器,删除掉罪魁祸首AutoRun
,再重启电脑就恢复正常了。
至此,历经千辛万苦,电脑总算是修好了,可算是不需要重装系统了。
4.附录
4.1.ANSI颜色序列格式
本段来自转义序列Escape Sequences及Linux echo命令多种颜色显示。
在计算机界,ANSI转义编码(escape code)或者转义序列(escape sequences)是带内信号(元数据和控制信号,译者注)控制视频文字终端的格式、颜色、其他输出选项的一种方法。
为了编码这些格式信息,它把某种字节序列嵌入到文本中,该序列必须特别的解释,且不应该作为字符的本义。
尽管硬件字符终端在21世纪已经变得很愈来愈少见,这种标准依然具有实用价值,是因为大多数终端仿真器至少还能解释在输出文本中的一些ANSI转义序列。
但微软的win32控制台组件就是一个明显的例外。
上文中的「\033[35m
」和「\033[0m
」就是ANSI转义序列(ANSI escape code/sequence),转义序列使用ESC控制字符开始,ESC键位于键盘左上角,其对应的ASCII码为\033(八进制)
、\27(十进制)
和\0x1b(十六进制)
。
通用的控制文本颜色的转义序列格式为CSI n1[;n2[;...]] m
,其中CSI
全称为「控制序列引导器(Control Sequence Introducer/Initiator)」,即上述\033
、\x1b
和\e
等;n1
、n2
等表示SGR参数,多个SGR参数可以组合使用,见下表。
通常,我们只需要用到表中部分属性,更详细的属性值可参考命令行里输出带颜色的字体。
一般格式:CSI[显示方式;前景色;背景色m 文字 CSI[0m
。
注:经测试,在Linux下
\033
、\x1b
和\e
可用,\33
、\0x1b
和\27
不可用。
注:在Windows下只有\033
、\33
、\x1b
、^[
可用(不一定准确),\e
不可用。
编码 | 说明 | 备注 |
---|---|---|
0 |
关闭所有格式,还原为初始状态 | 终端默认设置 |
1 |
粗体/高亮显示 | 无 |
2 |
模糊/弱化 | 不是所有的终端仿真器都支持,只有少数仿真器支持 |
3 |
斜体 | 不是所有的终端仿真器都支持,只有少数仿真器支持 |
4 |
下划线(单线) | 无 |
5 |
闪烁(慢) | 无 |
6 |
闪烁(快) | 不是所有的终端仿真器都支持,只有少数仿真器支持 |
7 |
交换背景色与前景色(反显) | 无 |
8 |
隐藏(伸手不见五指,啥也看不见) | 不是所有的终端仿真器都支持,只有少数仿真器支持 |
22 |
设置一般密度 | 无 |
24 |
关闭下划线 | 无 |
25 |
关闭闪烁 | 无 |
27 |
关闭反向图像,即关闭7 |
无 |
30-37 |
前景色,即30+x ,x 表示不同的颜色(参见下面的「颜色表」) |
无 |
38 |
在缺省的前景颜色上设置下划线 | 无 |
39 |
在缺省的前景颜色上关闭下划线 | 无 |
40-47 |
背景色,即40+x ,x 表示不同的颜色(参见下面的「颜色表」) |
无 |
49 |
设置缺省黑色背景 | 无 |
颜色值x |
前景色编码 | 背景色编码 | 颜色 | 效果 |
---|---|---|---|---|
0 |
30 |
40 |
黑色 | 黑色 |
1 |
31 |
41 |
红色 | 红色 |
2 |
32 |
42 |
绿色 | 绿色 |
3 |
33 |
43 |
黄色 | 黄色 |
4 |
34 |
44 |
蓝色 | 蓝色 |
5 |
35 |
45 |
紫色 | 紫色 |
6 |
36 |
46 |
青色 | 青色 |
7 |
37 |
47 |
白色 | 白色 |
4.2.设置颜色
一般格式:CSI
[
显示方式;
前景色;
背景色
m
文字部分
CSI
[
0
m
。
CSI |
显示方式 | 前景色 | 背景色 |
---|---|---|---|
\033 \x1b \e ESC(^[) |
0-9 等 |
30-37 |
40-47 |
需要说明的是,在同一处的CSI最好保持一致,「显示方式」、「前景色」和「背景色」的顺序不重要。
关于Windows下CMD中ESC(^[)
的输入方式,参考《Windows cmd(DOS)命令窗口中echo命令ANSI转义显示彩色字或背景》:
Windows下CMD中
^[
是ANSI的ESC一个字符(注意^
和[
是一个字符,就好比我们Ctrl + C
时显示的^C
一样),并不是我们看到的键盘上左上角那个ESC按键。其ASCII码值的十进制是27
, 八进制是33
(一般写为\033
),十六进制是1b
(一般写为\x1b
)。其输入方法有以下几种:
- 方法一(只能在CMD窗口中输入):在CMD窗口中按
Ctrl + [
组合键即可,这种方法最简单。- 方法二(只能在CMD窗口中输入):在CMD窗口中按
Alt + 2 + 7
组合键即可,注意必须是小键盘上的数字键2
和7
,先按住Alt
不放再按2
和7
最后放开Alt
。如果没有数字小键盘,则不能用这种方式。- 方法三(编辑器中先输入再替换):略。垃圾软件不配。