Хотя консольные окна в Windows 10 поддерживают управляющие последовательности VT (виртуальный терминал)/ANSI, в принципе, поддержка отключена по умолчанию .
У вас есть три варианта:
(a) Активировать поддержку глобально по умолчанию, постоянно через реестр, как описано в этот ответ SU.
- In short: In registry key
[HKEY_CURRENT_USER\Console]
, create or set the VirtualTerminalLevel
DWORD value to 1
- From PowerShell, you can do this programmatically as follows:
Set-ItemProperty HKCU:\Console VirtualTerminalLevel -Type DWORD 1
- От
cmd.exe
(также работает из PowerShell):
reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1
- Откройте новое окно консоли, чтобы изменения вступили в силу.
- См. предостережения ниже.
(b) Активируйте поддержку изнутри вашей программы только для этой программы (процесса), вызвав функцию SetConsoleMode()
Windows API.
(c) Специальный обходной путь, из PowerShell: направлять выходные данные из внешних программ в Out-Host
; например, .\test.exe | Out-Host
Re (a):
Подход на основе реестра неизменно активирует поддержку VT глобально, то есть для всех окон консоли, независимо от того, какая оболочка/программа в них запущена:
Отдельные исполняемые файлы/оболочки могут по-прежнему деактивировать поддержку для себя, при желании, с помощью метода (b).
Однако, наоборот, это означает, что вывод любой программы, которая явно не контролирует поддержку VT, будет подвергаться интерпретации последовательностей VT; хотя в целом это желательно, гипотетически это может привести к неправильной интерпретации выходных данных программ, которые случайно создают выходные данные с последовательностями, подобными VT.
Примечание:
Хотя существует существует механизм, который позволяет ограничивать параметры окна консоли запускаемым исполняемым файлом/заголовком окна через подключи [HKEY_CURRENT_USR\Console]
, значение VirtualTerminalLevel
, похоже, там не поддерживается.
Однако даже если бы это было так, это не было бы надежным решением, поскольку открытие окна консоли с помощью файла ярлыка (*.lnk
) (например, из меню «Пуск» или Bar) не будет учитывать эти настройки, потому что в *.lnk
файлах встроены настройки; в то время как вы можете изменить эти встроенные настройки через диалоговое окно графического интерфейса Properties
, на момент написания этой статьи параметр VirtualTerminalLevel
не отображался в этом графическом интерфейсе.
Re (b):
Вызов функции SetConsoleMode()
Windows API изнутри программы (процесса), как описано здесь, громоздко даже в C# (из-за необходимости объявления P/Invoke) и может не быть опцией:
для программ, написанных на языках, из которых вызов Windows API не поддерживается.
если у вас есть уже существующий исполняемый файл, который вы не можете изменить.
Если вы не хотите в этом случае включать глобальную поддержку (вариант (a)), вам может подойти вариант (c) (из PowerShell).
Re (c):
PowerShell автоматически активирует поддержку VT (виртуального терминала) для себя при запуске (в последних выпусках Windows 10 это относится как к Windows PowerShell, так и к PowerShell Core), но это не распространяется на внешние программы, вызываемые из PowerShell.
Однако если вы ретранслируете вывод внешней программы через PowerShell, последовательности VT распознаются; использование Out-Host
— самый простой способ сделать это (Write-Host
тоже подойдет):
.\t.exe | Out-Host
Примечание. Используйте Out-Host
, только если вы хотите печатать на консоль; если, напротив, вы хотите захватить вывод внешней программы, используйте только $capturedOutput = .\test.exe
Предупреждение о кодировке символов: Windows PowerShell по умолчанию ожидает, что выходные данные внешних программ будут использовать кодовую страницу OEM, как определено устаревшей локалью системы (например, 437
в англо-американских системах) и как отражено в [console]::OutputEncoding
. Консольные программы .NET автоматически учитывают этот параметр, но для программ, отличных от .NET (например, скриптов Python), которые используют другую кодировку (и производят не только чистый вывод ASCII (в 7-битном диапазоне)), вы должны (как минимум временно) укажите эту кодировку, присвоив [console]::OutputEncoding
; например, для UTF-8:
[console]::OutputEncoding = [Text.Encoding]::Utf8
.
Обратите внимание, что это необходимо не только для обхода VT-последовательностей, но и для правильного отображения символов, отличных от ASCII, в PowerShell. .
PowerShell Core, к сожалению, начиная с версии 6.1.0-preview.4 по умолчанию также использует кодовую страницу OEM, но это следует рассматривать как ошибку, учитывая, что PowerShell Core по умолчанию использует UTF-8 без BOM.
person
mklement0
schedule
04.08.2018