6

Windows 10 console host, conhost.exe, has native support for ANSI escape sequences, older versions do not. How can one detect the presence or absence of console ANSI support from a batch file?

Is it possible to call GetConsoleMode or other Windows API calls directly from a batch file?

jwfearn
  • 28,781
  • 28
  • 95
  • 122
  • 1
    You need PowerShell to call a Windows API, but you can call PowerShell from batch. – SomethingDark Jun 27 '16 at 01:51
  • @SomethingDark, can you recommend any good resources on how to call Windows APIs from Powershell? – jwfearn Jun 27 '16 at 02:26
  • 1
    Honestly, the one time I've ever needed to do it, I was lucky enough to only need to move and resize windows and I managed to find existing code that did exactly what I needed, but it's something like this: https://blogs.msdn.microsoft.com/mattbie/2010/02/23/how-to-call-net-and-win32-methods-from-powershell-and-your-troubleshooting-packs/ – SomethingDark Jun 27 '16 at 02:32
  • @Mofi: That's the old code-by-coincidence strategy, that never works out too well. The feature may get backported to Windows 8, so now your code fails to work on Windows 8. And there is [SetConsoleMode](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033.aspx), so you cannot blindly assume that virtual terminal sequences are always interpreted on Windows 10. And you really don't know what's the call on virtual terminal sequences in Windows v.Next. – IInspectable Jun 27 '16 at 07:43
  • @Mofi: That's an unfortunate decision, because now a future visitor will no longer know, that using `VER` had been considered, but was dismissed. Using `VER` leads to a solution that's not robust, and works by coincidence only. – IInspectable Jun 28 '16 at 07:23

1 Answers1

6

The answer to your last question is: Yes, with the aid of PowerShell code. This Batch file do what you requested:

@echo off
setlocal

set /A STD_OUTPUT_HANDLE=-11
set /A ENABLE_PROCESSED_OUTPUT=1, ENABLE_WRAP_AT_EOL_OUTPUT=2, ENABLE_VIRTUAL_TERMINAL_PROCESSING=4

PowerShell  ^
   $GetStdHandle = Add-Type 'A' -PassThru -MemberDefinition '  ^
      [DllImport(\"Kernel32.dll\")]  ^
      public static extern IntPtr GetStdHandle(int nStdHandle);  ^
   ';  ^
   $GetConsoleMode = Add-Type 'B' -PassThru -MemberDefinition '  ^
      [DllImport(\"Kernel32.dll\")]  ^
      public static extern bool GetConsoleMode(IntPtr hWnd, ref UInt32 lpMode);  ^
   ';  ^
   $StdoutHandle = $GetStdHandle::GetStdHandle(%STD_OUTPUT_HANDLE%);  ^
   $ConsoleMode = New-Object -TypeName UInt32;  ^
   $null = $GetConsoleMode::GetConsoleMode($StdoutHandle,[ref]$ConsoleMode);  ^
   Set-Content ConsoleMode.txt $ConsoleMode  ^
%End PowerShell%

set /P "ConsoleMode=" < ConsoleMode.txt
set /A "AnsiCompatible=ConsoleMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING"
if %AnsiCompatible% neq 0 (
   echo The console is Ansi-compatible!
) else (
   echo Ansi codes not supported...
)

I wrote this type of code reading the examples at the PowerShell help on Add-Type cmdlet and the info given in the accepted answer at this question.

Community
  • 1
  • 1
Aacini
  • 65,180
  • 12
  • 72
  • 108