J'ai écrit un programme qui imprime une chaîne, qui contient séquences d'échappement ANSI pour colorer le texte. Mais cela ne fonctionne pas comme prévu dans la console Windows 10 par défaut, comme vous pouvez le voir sur la capture d'écran.
La sortie du programme apparaît avec les séquences d'échappement sous forme de caractères imprimés. Si j'introduis cette chaîne dans PowerShell via une variable ou une tuyauterie, la sortie apparaît comme prévu (texte rouge).
Comment puis-je obtenir que le programme imprime du texte en couleur sans aucune solution?
Ceci est ma source de programme (Haskell) - mais le langage n'est pas pertinent, juste pour que vous puissiez voir comment les séquences d'échappement sont écrites.
main = do
let red = "\ESC[31m"
let reset = "\ESC[39m"
putStrLn $ red ++ "RED" ++ reset
Alors que les fenêtres de console dans Windows 10 prennent en charge les séquences d'échappement VT (Virtual Terminal)/ANSI en principe, le support est désactivé OFF par défaut.
Vous avez trois options:
(a) Activer le support globalement par défaut, de façon persistante, via le registre, comme détaillé dans this Réponse S .
[HKEY_CURRENT_USER\Console]
, Créez ou définissez la valeur DWORD VirtualTerminalLevel
sur 1
Set-ItemProperty HKCU:\Console VirtualTerminalLevel -Type DWORD 1
cmd.exe
(Fonctionne également depuis PowerShell):reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1
(b) Activez le support depuis l'intérieur de votre programme, pour ce programme (processus) uniquement, avec un appel à la SetConsoleMode()
Fonction API Windows.
(c) Solution de contournement ad-hoc, de PowerShell: redirige la sortie des programmes externes vers Out-Host
; par exemple, .\test.exe | Out-Host
L'approche basée sur le registre active invariablement le support VT globalement, c'est-à-dire pour all les fenêtres de console , indépendamment de ce que Shell/programme y exécute:
Les exécutables/shells individuels peuvent toujours désactiver le support d'eux-mêmes, si vous le souhaitez, en utilisant la méthode (b).
Inversement, cependant, cela signifie que la sortie de tout programme qui ne contrôle pas explicitement le support VT sera sujette à l'interprétation des séquences VT; bien que cela soit généralement souhaitable, cela pourrait hypothétiquement conduire à une mauvaise interprétation de la sortie de programmes qui accidentellement produisent une sortie avec des séquences de type VT.
Remarque:
Alors qu'il existe est un mécanisme qui permet aux paramètres de la fenêtre de la console d'être étendus par le titre de l'exécutable/de la fenêtre de démarrage, via sous-clés de [HKEY_CURRENT_USR\Console]
, Le VirtualTerminalLevel
la valeur ne semble pas y être prise en charge.
Même si c'était le cas, cependant, ce ne serait pas une solution robuste, car ouvrir une fenêtre de console via un fichier raccourci (*.lnk
) (par exemple à partir du menu Démarrer ou de la barre des tâches) ne respecterait pas ces paramètres, car les fichiers *.lnk
ont des paramètres intégrés; bien que vous puissiez modifier ces paramètres intégrés via la boîte de dialogue de l'interface graphique Properties
, à ce jour, le paramètre VirtualTerminalLevel
n'est pas indiqué dans cette interface graphique.
L'appel de la fonction SetConsoleMode()
API Windows depuis l'intérieur du programme (processus), comme décrit ici , est fastidieux même en C # (en raison de la nécessité d'un P/Invoke declaration), et peut ne pas être une option :
pour les programmes écrits dans des langues à partir desquelles l'appel de l'API Windows n'est pas pris en charge.
si vous avez un exécutable préexistant que vous ne pouvez pas modifier.
Si vous ne souhaitez pas activer la prise en charge globale dans ce cas (option (a)), l'option (c) (de PowerShell) peut fonctionner pour vous.
PowerShell active automatiquement la prise en charge VT (terminal virtuel) pour lui-même au démarrage (dans les versions récentes de Windows 10, cela s'applique Windows PowerShell et PowerShell Core).
Par conséquent, si vous relais la sortie d'un programme externe via PowerShell, les séquences VT sont reconnues ; utiliser Out-Host
est le moyen le plus simple de le faire (Write-Host
fonctionnerait aussi):
.\t.exe | Out-Host
Remarque: Utilisez Out-Host
Uniquement si vous souhaitez imprimer sur la console; si, au contraire, vous voulez capturer la sortie du programme externe, utilisez simplement $capturedOutput = .\test.exe
Avertissement de codage de caractères : Windows PowerShell attend par défaut que la sortie des programmes externes utilise la page de codes OEM, telle que définie par les paramètres régionaux du système hérité (par exemple, 437
Sur les systèmes US-English) et comme indiqué dans [console]::OutputEncoding
. Les programmes de la console .NET respectent ce paramètre automatiquement, mais pour les programmes non .NET (par exemple, les scripts Python) qui utilisent un codage différent (et produisent non seulement une sortie pure ASCII (dans le 7 bits)), vous devez (au moins temporairement) spécifier cet encodage en l'assignant à [console]::OutputEncoding
; par exemple, pour UTF-8:[console]::OutputEncoding = [Text.Encoding]::Utf8
.
Notez que ceci est non seulement nécessaire pour la solution de contournement des séquences VT, mais généralement nécessaire pour que PowerShell restitue correctement les caractères non ASCII .
PowerShell Core, malheureusement, à partir de la version 6.1.0-preview.4, la page de codes OEM est également par défaut, mais cela devrait être considéré comme un bug , étant donné que PowerShell Core par défaut est UTF-8 sans BOM.
Merci à l'utilisateur mklement0 de m'avoir informé que le support VT n'est pas activé automatiquement. Cela m'a fait regarder dans la bonne direction et j'ai trouvé ce message utile .
Donc, pour répondre à ma question: ajouter ou définir la clé de registre
HKCU:\Console - [DWORD] VirtualTerminalLevel = 1
Redémarrez la console et cela fonctionne.