Click here to Skip to main content
15,445,997 members
Articles / Programming Languages / C++
Posted 5 Jan 2007


74 bookmarked

Add Colors to Batch Files

Rate me:
Please Sign up or sign in to vote.
4.94/5 (31 votes)
24 Aug 2010CPOL4 min read
An enhanced ECHO command line utility with color support.

Colorize Batch File


Batch files are useful to deal with repetitive tasks. However, they lack some user-friendly features such as colorizing console outputs. Colorized outputs might be useful to draw attention to important information. The Win32 API provides some useful functions to interact with the console (see Console Functions in MSDN). But in your batch files, the only command available is COLOR. The COLOR command only defines the color of the entire window console.

cecho is an enhanced ECHO command line utility with color support, inspired by the CTEXT utility by Dennis Bareis.

The last section explains how to embed the cecho utility into a batch file using the Debug.exe program (until Windows Vista).

Using the Code

cecho simply redirects the command arguments to the standard output after parsing color information. cecho arguments include:

  • {XX}: colors coded as two hexadecimal digits. E.g., {0A} light green
  • {color}: color information as understandable text. E.g., {light red on black}
  • {\n \t}: New line character - Tab character.
  • {\u0000}: Unicode character code.
  • {{: escape character '{'.
  • {#}: restore initial colors.

Available colors:

0 = black8 = gray
1 = navy9 = blue
2 = greenA = lime
3 = tealB = aqua
4 = maroonC = red
5 = purpleD = fuchsia
6 = oliveE = yellow
7 = silverF = white

Sample batch file:

@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


Changes log: in cecho v2.0, the {0x00} ASCII code has been replaced by the {\u0000} Unicode character.

Inside cecho

Colorized Console Output

Colorizing console output is pretty straightforward. Simply call the SetConsoleTextAttribute Win32 API with the correct color code. All further console outputs will be displayed in the specified color. We'll explain tokStack later.

void setColor()
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    tokStack[tokCurs-1] = 0;
    SetConsoleTextAttribute(hConsole, (WORD)strtol(tokStack, 0, 16));

Parsing Command Arguments

According to the cecho documentation, parsing command arguments can be described by the following parse tree:

Parse Tree

Fig. 1: Parse Tree

The parse tree grammar in C language becomes:

#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" \t", L"}", L"\\"},
    {L"0123456789abcdefABCDEF", L""},
    {L"}", L""},
    {L"}", L""}

// action executed on state changed
Fct Action[][MAX_TRANS] = {

// next state Ids
char Successor[][MAX_TRANS] = {

The parser state chart contains 7 states. The Grammar array stores lists of expected tokens that trigger a transition for a specific state. An empty list acts as the wild char token. The Action array maintains pointers to the function to execute during a specific transition. The Successor array identifies the next state for each transition.

The parser engine iterates through all input characters. If the character triggers an outgoing transition of the current parser state, then the character is added to the tokStack token stack, the action associated with the transition (if any) is executed, and the parser state is updated.

// 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)
                    tokCurs = 0; // reset token stack
                // update parser state
                state = Successor[state][trans];
                fired = 1;
        if (fired == 0)
            wprintf(L"Syntax error: '%c' col %i", *token, input - token);
            return -1;
    // print remaing token stack
    return 0;

The Action's functions are quite simple and aren't worth any comments.

Annexe: How to embed cecho.exe inside a batch file

Note: Debug.exe has been phased out in Windows 7. I keep this section for reference, but I no longer recommend using it.

The embedding mechanism relies on the Debug.exe program. The cecho binary is converted to a debug script using the BIN2DBG.EXE utility by Anthony Caruso. The debug script is then embedded in the batch file. At run time, the debug script is processed by Debug.exe to recreate the cecho executable file.

  1. Convert cecho.exe into cecho.dbg using BIN2DBG.EXE.
  2. C:\>bin2dbg.exe cecho.exe
  3. Edit cecho.dbg with a text editor. Modify the file extension on the first line of cecho.dbg because Debug.exe is not allowed to write an EXE file. Use a *.com extension, for instance.
  4. n
    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 
  5. Include cecho.dbg into your batch file. Your batch file must reconstruct exactly the same cecho.dbg file. A batch command could be useful:
  6. C:\>for /f "delims=" %l in (cecho.dbg) do (echo echo %l ^>^> tmp.dbg >> cecho.bat)
  7. Add commands to rebuild (formerly cecho.exe) to the end of cecho.bat.
  8. ...
    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

    The trick with the tmp.bat file and the start /wait /min command is detailed by Jakob Bohm in the forum section of this article: Possible reason for the start /min /wait trick. It basically runs the 16 bit DOS Debug.exe in a separate console to prevent file handles from remaining open.

  9. We're done! cecho is now available and ready to colorize your batch output.
  10. ...
    call :unpack_cecho
    REM is now available for use. {red}This line in red{#}
    goto :eof

Because the debug script size is much bigger than the EXE size, we need to keep cecho.exe as small as possible. The UPX executable packer reduces cecho.exe (compiled with VC++10) by 50%.

I also suggest to include the debug script as a "function" in your batch file. See the batch function syntax by Ritchie Laurence.


  • Initial release - January 03, 2007
  • Minor changes - August 07, 2007
    • Added the "start /min /wait" trick and reduced the EXE size with UPX.
  • cecho v2.0 - August 23, 2010
    • Added Unicode support.
    • Added x64 support.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

Bugfuchsia not fuchisa Pin
AniAnti26-Feb-21 5:38
MemberAniAnti26-Feb-21 5:38 
PraiseThanks for create Cecho Pin
Member 148775744-Jul-20 19:06
MemberMember 148775744-Jul-20 19:06 
QuestionThanks Pin
silverBullet.8812-Feb-20 13:17
MembersilverBullet.8812-Feb-20 13:17 
PraiseThanks this is cool Pin
Member 1471845625-Jan-20 8:57
MemberMember 1471845625-Jan-20 8:57 
Questionembed Pin
Member 1406397923-Nov-18 7:14
MemberMember 1406397923-Nov-18 7:14 
GeneralThanks for making this! Pin
Burn_E993-Sep-15 7:59
MemberBurn_E993-Sep-15 7:59 
QuestionReally Like This, Thank You! Pin
Mark Regal4-Sep-14 15:19
MemberMark Regal4-Sep-14 15:19 
QuestionCarriage returns and parens Pin
WilliamByrne18-Feb-13 23:30
MemberWilliamByrne18-Feb-13 23:30 
Questionswitch back to default background color Pin
hl_2-May-12 6:59
Memberhl_2-May-12 6:59 
AnswerRe: switch back to default background color Pin
Thomas Polaert2-May-12 7:24
MemberThomas Polaert2-May-12 7:24 
Generalspaces are ignored Pin
erkanozkan26-Feb-10 5:42
Membererkanozkan26-Feb-10 5:42 
GeneralRe: spaces are ignored Pin
Thomas Polaert26-Feb-10 6:41
MemberThomas Polaert26-Feb-10 6:41 
GeneralRe: spaces are ignored Pin
erkanozkan26-Feb-10 8:09
Membererkanozkan26-Feb-10 8:09 
GeneralRe: spaces are ignored Pin
Thomas Polaert24-Aug-10 2:18
MemberThomas Polaert24-Aug-10 2:18 
GeneralDefault Color Pin
Member 540677917-Jan-10 19:13
MemberMember 540677917-Jan-10 19:13 
QuestionVery special request to the author... 64 bits for WinRE 64 bit? Pin
J. Gabriel Santos9-Dec-09 18:50
MemberJ. Gabriel Santos9-Dec-09 18:50 
AnswerRe: Very special request to the author... 64 bits for WinRE 64 bit? Pin
Thomas Polaert18-Dec-09 6:26
MemberThomas Polaert18-Dec-09 6:26 
GeneralRe: Very special request to the author... 64 bits for WinRE 64 bit? Pin
J. Gabriel Santos31-Dec-09 8:42
MemberJ. Gabriel Santos31-Dec-09 8:42 
GeneralWindows Vista Pin
Codiah18-Sep-09 20:35
MemberCodiah18-Sep-09 20:35 
GeneralRe: Windows Vista Pin
Thomas Polaert20-Sep-09 22:01
MemberThomas Polaert20-Sep-09 22:01 
QuestionFree to distribute? Pin
psonar14-Apr-08 17:27
Memberpsonar14-Apr-08 17:27 
AnswerRe: Free to distribute? Pin
Thomas Polaert14-Apr-08 22:11
MemberThomas Polaert14-Apr-08 22:11 
Generalslightly smaller embedded code Pin
remailer6-Aug-07 13:50
Memberremailer6-Aug-07 13:50 
GeneralRe: slightly smaller embedded code Pin
Thomas Polaert7-Aug-07 5:32
MemberThomas Polaert7-Aug-07 5:32 
GeneralPossible reason for the start /min /wait trick Pin
Jakob Bohm10-Jan-07 1:36
MemberJakob Bohm10-Jan-07 1:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.