为批处理文件添加颜色






4.96/5 (31投票s)
一个增强的带颜色支持的 ECHO 命令行实用程序。
引言
批处理文件对于处理重复性任务非常有用。但是,它们缺少一些用户友好的功能,例如彩色控制台输出。彩色输出可能有助于吸引对重要信息的注意。Win32 API 提供了一些有用的函数来与控制台进行交互(请参阅 MSDN 中的 Console Functions)。但在您的批处理文件中,唯一可用的命令是 COLOR
。COLOR
命令仅定义整个窗口控制台的颜色。
cecho 是一个增强的带颜色支持的 ECHO 命令行实用程序,灵感来自 Dennis Bareis 的 CTEXT 实用程序。
最后一节解释了如何使用 Debug.exe 程序(直到 Windows Vista)将 cecho 实用程序嵌入到批处理文件中。
Using the Code
cecho 在解析颜色信息后,简单地将命令参数重定向到标准输出。cecho 参数包括:
{XX}
:颜色代码,由两个十六进制数字组成。例如,{0A} 浅绿色{color}
:易于理解的文本形式的颜色信息。例如,{light red on black}{\n \t}
:换行符 - 制表符。{\u0000}
:Unicode 字符代码。{{
:转义字符 '{'。{#}
:恢复初始颜色。
可用颜色
0 = 黑色 | 8 = 灰色 |
1 = 藏青色 | 9 = 蓝色 |
2 = 绿色 | A = 亮绿色 |
3 = 青色 | B = 水色 |
4 = 栗色 | C = 红色 |
5 = 紫色 | D = 洋红色 |
6 = 橄榄色 | E = 黄色 |
7 = 银色 | F = 白色 |
示例批处理文件
@echo off
cecho {0C}This line is red{#}
REM Print ASCII char 0x07 (beep)
cecho {\u07 \u07}
cecho This {black on blue}word{#} is black on a blue background
...
更改日志:在 cecho v2.0 中,{0x00} ASCII 代码已被 {\u0000} Unicode 字符替换。
cecho 内部
彩色控制台输出
对控制台输出进行着色相当直接。只需调用 SetConsoleTextAttribute
Win32 API 并传入正确的颜色代码。所有后续的控制台输出都将以指定的颜色显示。我们稍后会解释 tokStack
。
void setColor()
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
tokStack[tokCurs-1] = 0;
SetConsoleTextAttribute(hConsole, (WORD)strtol(tokStack, 0, 16));
}
解析命令行参数
根据 cecho 文档,命令行参数的解析可以由以下解析树描述:
C 语言中的解析树语法变为:
#define MAX_TRANS 5
// expected tokens list
wchar_t* Grammar[][MAX_TRANS] = {
{L"{", L""},
{L"{}", L"\\", L"0123456789abcdefABCDEF", L" \t", L""},
{L"tn", L"u"},
{L"0123456789abcdefABCDEF"},
{L"0123456789abcdefABCDEF", L" \t", L"}", L"\\"},
{L"0123456789abcdefABCDEF", L""},
{L"}", L""},
{L"}", L""}
};
// action executed on state changed
Fct Action[][MAX_TRANS] = {
{&printStack,0},
{&resetStack,0,0,0,0},
{&printEscChar,0},
{0},
{0,&printHexChar,&printHexChar,&printHexChar},
{0,0},
{&setColor,0},
{&parseColor,0}
};
// next state Ids
char Successor[][MAX_TRANS] = {
{1,0},
{0,2,5,1,7},
{1,3},
{4},
{4,1,0,2},
{6,7},
{0,7},
{0,7}
};
解析器状态图包含 7 个状态。Grammar
数组存储预期标记的列表,这些标记会触发特定状态的转换。空列表充当通配符标记。Action
数组维护指向在特定转换期间执行的函数的指针。Successor
数组标识每个转换的下一个状态。
解析器引擎会遍历所有输入字符。如果字符触发了当前解析器状态的传出转换,则该字符将被添加到 tokStack
标记堆栈中,执行与转换关联的操作(如果有),然后更新解析器状态。
// token stack
wchar_t tokStack[MAX_STACK];
// token stack cursor
int tokCurs = 0;
int wmain(int argc, wchar_t* argv[])
{
short trans, clr, fired;
wchar_t* token;
char state = 0;
[...]
// retrieve command argument
LPWSTR input = GetCommandLineW();
if (*input == L'"')
input += 2;
input += wcslen(argv[0]) + 1;
// parse input string
for (fired = 0, token = input; *token != 0; token++)
{
// does token trigger a transition ?
for (trans = 0; trans < MAX_TRANS && Grammar[state][trans] != 0; trans++)
{
// check if token belongs to the expected tokens list ?
// a empty list acts as a wildchar token
if (wcschr(Grammar[state][trans], *token) || *Grammar[state][trans] == 0)
{
// push token into the stack
if (tokCurs < MAX_STACK)
tokStack[tokCurs++] = *token;
// execute the action associated to the transition (if any)
if (Action[state][trans] != 0)
{
(*Action[state][trans])();
tokCurs = 0; // reset token stack
}
// update parser state
state = Successor[state][trans];
fired = 1;
break;
}
}
if (fired == 0)
{
wprintf(L"Syntax error: '%c' col %i", *token, input - token);
return -1;
}
}
// print remaing token stack
tokCurs++;
printStack();
return 0;
}
Action
中的函数非常简单,不值得在此进行评论。
附录:如何将 cecho.exe 嵌入到批处理文件中
注意:Debug.exe 已在 Windows 7 中淘汰。我保留此部分仅供参考,但不再推荐使用它。
嵌入机制依赖于 Debug.exe 程序。cecho 二进制文件使用 Anthony Caruso 的 BIN2DBG.EXE 工具转换为调试脚本。然后将调试脚本嵌入到批处理文件中。在运行时,Debug.exe 会处理调试脚本以重新创建 cecho 可执行文件。
- 使用 BIN2DBG.EXE 将 cecho.exe 转换为 cecho.dbg。
- 使用文本编辑器编辑 cecho.dbg。修改 cecho.dbg 第一行的文件扩展名,因为 Debug.exe 不允许写入 EXE 文件。例如,使用 *.com 扩展名。
- 将 cecho.dbg 包含到您的批处理文件中。您的批处理文件必须完全重建相同的 cecho.dbg 文件。可以使用批处理命令
- 在 cecho.bat 的末尾添加命令以重新构建 cecho.com(以前是 cecho.exe)。
- 我们完成了!cecho 现在可用,并准备好为您的批处理输出添加颜色。
C:\>bin2dbg.exe cecho.exe
n cecho.com
e 100 4D 5A 90 0 3 0 0 0 4 0 0 0 FF FF 0 0
e 110 B8 0 0 0 0 0 0 0 40 0 0 0 0 0 0 0
e 120 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
...
C:\>for /f "delims=" %l in (cecho.dbg) do (echo echo %l ^>^> tmp.dbg >> cecho.bat)
...
echo e 10E0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 >> tmp.dbg
echo e 10F0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 >> tmp.dbg
echo e 1100 0 >> tmp.dbg
echo rcx >> tmp.dbg
echo 1000 >> tmp.dbg
echo w >> tmp.dbg
echo q >> tmp.dbg
echo debug ^< tmp.dbg > tmp.bat
echo exit >> tmp.bat
start /wait /min tmp.bat
del tmp.bat
del tmp.dbg
tmp.bat 文件和 start /wait /min 命令的技巧由 Jakob Bohm 在本文的论坛部分详细介绍:Possible reason for the start /min /wait trick。它基本上是在一个单独的控制台中运行 16 位 DOS Debug.exe,以防止文件句柄保持打开状态。
...
call :unpack_cecho
REM cecho.com is now available for use.
cecho.com {red}This line in red{#}
...
del cecho.com
goto :eof
由于调试脚本的大小比 EXE 文件大得多,我们需要尽可能减小 cecho.exe 的尺寸。 UPX 可执行文件打包器将 cecho.exe(使用 VC++10 编译)减小了 50%。
我还建议将调试脚本作为“函数”包含在您的批处理文件中。请参阅 Ritchie Laurence 的批处理函数语法。
历史
- 初始发布 - 2007 年 1 月 3 日
- 次要更改 - 2007 年 8 月 7 日
- 添加了“start /min /wait”技巧,并使用 UPX 减小了 EXE 尺寸。
- cecho v2.0 - 2010 年 8 月 23 日
- 添加了 Unicode 支持。
- 添加了 x64 支持。