Warum?
Die neue Windows Console unterstützt beginnend mit Windows 10.0.10586 ANSI Escapesequenzen im Virtual Terminal Modus, beispielsweise um Text farbig auszugeben. Siehe:
Consoleanwendungen müssen die Console aber zunächst konditionieren um diese Escapesequenzen auch nutzen zu können.
Ziele dieser kleinen Lib sind:
Wie?
Zwei Dinge sind zu berücksichtigen, die völlig unabhängig voneinander existieren.
Darüber hinaus ist die
Detaillierte Beschreibungen finden sich im
Der folgende Testcode zeigt beispielhaft, wie mit der Lib zu arbeiten ist ("win10vt.h" und "win10vt.c" sind in das Projekt eingebunden und finden sich im Download.):
Statt den C Ausgabefunktionen, könnten hier auch die C++ Ausgabestreams
Dieses Batch Script ruft die kompilierte "enable_ansi_esc.exe" unter unterschiedlichen Konditionen auf. Hier soll gezeigt werden, dass der obige C Code tatsächlich in der Lage war zu erkennen, wo VT Processing möglich ist und wo nicht:
Ausgabe:
Die Ausgabe ist wie folgt zu interpretieren:
Die neue Windows Console unterstützt beginnend mit Windows 10.0.10586 ANSI Escapesequenzen im Virtual Terminal Modus, beispielsweise um Text farbig auszugeben. Siehe:

Console Virtual Terminal Sequences - Windows Console
Virtual terminal sequences are control character sequences that can control cursor movement, color/font mode, and other operations when written to the output stream.
docs.microsoft.com
Ziele dieser kleinen Lib sind:
- Auskapseln der erforderlichen Windows API aus dem Benutzercode.
- Konditionierung der Windows Console für den VT Modus, bzw. dessen Deaktivierung.
- Identifikation der Standardstreams die im VT Modus verwendbar sind, um verhindern zu können, Escapesequenzen auszugeben, die nicht gerendert werden und stattdessen in ihrer Textrepräsentation verarbeitet werden.
Wie?
Zwei Dinge sind zu berücksichtigen, die völlig unabhängig voneinander existieren.
- Das Consolefenster besitzt einen Eingabe- und einen Ausgabepuffer. Für beide kann der VT Modus im Hostprozess konfiguriert werden, sofern die Anwendung mit einem Consolefenster verknüpft ist und es sich um das neue Windows 10 V2 Consolefenster handelt (conhost.exe ohne angegliederten cscss.exe Runtime Prozess). Ob diese Konfiguration möglich oder nicht möglich ist, gibt letztlich darüber Aufschluss und ist eines der Entscheidungskriterien ob mit Escapesequenzen gearbeitet werden kann. Die
SetVTConMode
Funktion ist zu diesem Zweck implementiert. - Wenn das Consolefenster konfiguriert werden konnte, bedeutet das noch nicht, dass die Standardeingabe, Standardausgabe und Standardfehlerausgabe auch mit diesem verknüpft sind. Die entsprechenden Handles können durchaus auf eine Datei oder eine Pipe umgeleitet sein, wo Escapesequenzen nicht gerendert werden können. Der Rückgabewert der
GetStdReferCon
Funktion beinhaltet Informationen, ob das StdIn auf ConIn, und ob StdOut und StdErr auf ConOut verweisen.
Darüber hinaus ist die
TargetIsWindowsConsole
Funktion implementiert, die Aussage darüber gibt, ob an den derzeitigen Prozess überhaupt eine Windows Console angehängt ist. Bei anderen Virtual Terminal Anwendungen ist oft davon auszugehen, dass sie VT Escapesequenzen von vorn herein unterstützen.Detaillierte Beschreibungen finden sich im
win10vt.h
Header im Download.Der folgende Testcode zeigt beispielhaft, wie mit der Lib zu arbeiten ist ("win10vt.h" und "win10vt.c" sind in das Projekt eingebunden und finden sich im Download.):
enable_ansi_esc.c:
#include "win10vt.h"
#include <stdio.h>
int main(void) {
// Figure out which of the standard handles refer to the console window (rather than to a file or a pipe).
unsigned con_connected = GetStdReferCon();
// Try to enable VT processing for the handles of the attached console window, and retrieve for which it happened to work.
unsigned vt_enabled = SetVTConMode(VT_CONALL, VT_CONALL);
if ((vt_enabled & VT_CONOUT) && (con_connected & VT_STDOUT)) // VT sequences can be used for stdout.
{
fputs(ESC([42m) "Hello Narrow World!\n" ESC([0m), stdout);
fputws(ESCW([42m) L"Hello Wide World!\n" ESCW([0m), stdout);
} else // VT sequences not supported for stdout.
{
fputs("Hello Narrow World!\n", stdout);
fputws(L"Hello Wide World!\n", stdout);
}
if ((vt_enabled & VT_CONOUT) && (con_connected & VT_STDERR)) // VT sequences can be used for stderr.
fputs(ESC([41m) "Hello Wrong World!\n" ESC([0m), stderr);
else // VT sequences not supported for stderr.
fputs("Hello Wrong World!\n", stderr);
// Disable VT processing for the handles of the attached console window to be sure subsequent tests are not influenced.
SetVTConMode(VT_CONALL, VT_CONNONE);
return 0;
}
std::cout
, std::wcout
und std::cerr
oder die entsprechenden Windows API Funktionen wie WriteFile
zum Einsatz kommen, um die Effekte zu testen. Das Resultat bliebe gleich.Dieses Batch Script ruft die kompilierte "enable_ansi_esc.exe" unter unterschiedlichen Konditionen auf. Hier soll gezeigt werden, dass der obige C Code tatsächlich in der Lage war zu erkennen, wo VT Processing möglich ist und wo nicht:
test.bat:
@echo off &setlocal
echo(
echo(*** directly
enable_ansi_esc
echo(
echo(*** pipe (err merged)
enable_ansi_esc 2>&1 | find /v ""
echo(
echo(*** pipe
enable_ansi_esc | find /v ""
echo(
echo(*** for (err merged)
for /f "delims=" %%i in ('2^>^&1 enable_ansi_esc') do echo %%i
echo(
echo(*** for
for /f "delims=" %%i in ('enable_ansi_esc') do echo %%i
echo(
echo(*** redirect to con (err merged)
>con 2>&1 enable_ansi_esc
echo(
echo(*** redirect to con
>con enable_ansi_esc
echo(
pause
Ausgabe:
Die Ausgabe ist wie folgt zu interpretieren:
- Wo VT Processing möglich war, erfolgt die Ausgabe farbig (grün bzw. rot). Standardfarben weiß auf schwarz dort, wo VT Prozessing nicht möglich ist.
- Bei einer fehlerhaften Entscheidung im Programmcode würde bei den weiß auf schwarz Ausgaben der Escapecode als Text ausgegeben werden, was aber nicht der Fall ist.