Enable ANSI escape sequence within Windows 10 console

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
dbenham
Expert
Posts: 2288
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Enable ANSI escape sequence within Windows 10 console

#1 Post by dbenham » 15 May 2019 10:57

Starting with Windows 10, the console supports ANSI escape sequences, but only if the console is configured to NOT "use legacy console", and the program writing to the console must configure its output to interpret the sequences.

CMD.EXE was modified such that its internal commands do support the ANSI sequences. For example, the ANSI sequences are active if you TYPE a file that contains them, or ECHO a string that contains them.

But external commands like FINDSTR and CSCRIPT do not enable the ANSI escape sequences. So the file that worked with TYPE does not work when using FINDSTR.

But I recently learned that the above behavior is just the default :!: Over at SuperUser.com I learned of a registry setting that enables ANSI escape sequences for all console programs that do not explicitly disable them :D
SuperUser.com user Glenn Slayden wrote: Fortunately, the global default can be changed from opt-in to opt-out. The registry key at HKEY_CURRENT_USER\Console\VirtualTerminalLevel sets the global default behavior for processing ANSI escape sequences. Create a DWORD key (if necessary) and set its value to 1 to globally enable (or 0 to disable`) ANSI processing by default.

Code: Select all

[HKEY_CURRENT_USER\Console]
"VirtualTerminalLevel"=dword:00000001
Note that this registry setting controls a default, meaning that it only affects console apps which don't explicitly manipulate the console mode by calling SetConsoleMode(...). It follows that, while the registry value may help enable ANSI for console-mode-oblivious apps, it will have no effect on any console-mode-savvy app which (for some reason) may explicitly disable ANSI.
For me this information is important because it enabled me to add a "highlight matched/replaced text' feature to my JREPL.BAT regular expression text processor. I plan to release version 8 imminently.


Dave Benham

aGerman
Expert
Posts: 3750
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Enable ANSI escape sequence within Windows 10 console

#2 Post by aGerman » 15 May 2019 12:15

Recently I read about this registry value, looked it up on my machine, but didn't find it. Since VT processing works for me I realized it was enabled by the script interpreters (such as cmd and powershell). But I didn't think about other console utilities. Thanks for the heads-up, Dave!

Steffen

aGerman
Expert
Posts: 3750
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Enable ANSI escape sequence within Windows 10 console

#3 Post by aGerman » 16 May 2019 10:18

Dave,
I hoped it would be possible to enable the VT mode in JREPL without updating the registry. Actually it works, but it's terribly slow. So, I'm afraid this is not an option :(
For testing, add that piece of code at the beginning of the JScript portion:

Code: Select all

var objExec = WScript.CreateObject("WScript.Shell").Exec("powershell.exe -nop -ep Bypass -c \"$c=Add-Type -Name pInv -PassThru -MemberDefinition '"
+ "[DllImport(\\\"kernel32.dll\\\")] public static extern IntPtr GetConsoleWindow();"
+ "[DllImport(\\\"kernel32.dll\\\")] public static extern int GetConsoleMode(IntPtr hConsoleHandle,ref int lpMode);"
+ "[DllImport(\\\"kernel32.dll\\\")] public static extern int SetConsoleMode(IntPtr hConsoleHandle,int dwMode);';"
+ "$m=0;$null=$c::GetConsoleMode($c::GetConsoleWindow(),[ref]$m);$m=$m -bOr 12;$null=$c::SetConsoleMode($c::GetConsoleWindow(),$m);\"");
while (objExec.Status == 0) {WScript.Sleep(50);}
Steffen

dbenham
Expert
Posts: 2288
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Enable ANSI escape sequence within Windows 10 console

#4 Post by dbenham » 16 May 2019 11:08

Very cool 8)

But yes, slow. Even so, I think it may be worth adding as an additional option. Maybe /VT to enable the escape sequences, for those that are desperate for the feature and willing to wait for the slow initialization.

JREPL already has significant startup time, and as you have it, there is effectively no parallel processing. Perhaps I can shave off a bit of the delay by initiating objExec early on, and postpone the while loop that checks the status until just before the main JREPL processing loop.

I suspect that the new Windows Terminal will support the escape sequences, at which point it may approach being a moot point.

Thanks Steffen.


Dave Benham

aGerman
Expert
Posts: 3750
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Enable ANSI escape sequence within Windows 10 console

#5 Post by aGerman » 16 May 2019 12:37

dbenham wrote:
16 May 2019 11:08
Perhaps I can shave off a bit of the delay by initiating objExec early on, and postpone the while loop that checks the status until just before the main JREPL processing loop.
Good idea :!: That reduced the delay to somewhat between a second or two when I tried it.
dbenham wrote:
16 May 2019 11:08
I suspect that the new Windows Terminal will support the escape sequences
I'm sure it will. But still I didn't understand if console scripts and apps will open in the terminal by default. My current understanding is that the terminal is an additional application where you can run console programs in. But it will not replace the console window.

Steffen

aGerman
Expert
Posts: 3750
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Enable ANSI escape sequence within Windows 10 console

#6 Post by aGerman » 17 May 2019 05:07

LOL :lol: New discovery ...

Try

Code: Select all

var objExec = WScript.CreateObject("WScript.Shell").Exec("powershell.exe -nop -ep Bypass -c \"exit\"");
while (objExec.Status == 0) {WScript.Sleep(50);}
Once you run powershell.exe VT processing keeps being persistent.
This is much faster :!: Unfortunately it doesn't work using cmd.exe which would have been even faster. The cmd seems to reset VT processing before it terminates.

Steffen

dbenham
Expert
Posts: 2288
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Enable ANSI escape sequence within Windows 10 console

#7 Post by dbenham » 19 May 2019 19:33

aGerman wrote:
17 May 2019 05:07
This is much faster :!:
I can't really tell. The first time I launch PowerShell within a given cmd.exe process, it is always S... L... O.... W.......
Thereafter it is relatively fast.
aGerman wrote:
17 May 2019 05:07
Unfortunately it doesn't work using cmd.exe which would have been even faster. The cmd seems to reset VT processing before it terminates.
Yea, at one point I tried to have PowerShell launch a new cmd.exe process, and was disappointed that it did not preserve the enabled escape sequences.


Thanks for the code Steffen. I opted to allow /VT without /H or /HU. Unlikely, but it is possible a source file could already have escape sequences, or they could be introduced by a find/replace without using /H or /HU.


Dave Benham

aGerman
Expert
Posts: 3750
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Enable ANSI escape sequence within Windows 10 console

#8 Post by aGerman » 20 May 2019 10:02

dbenham wrote:
19 May 2019 19:33
I can't really tell.
It saves the time wasted to write a temporary C# code and compile it into a DLL. Platform invocation (the 3 lines between the single quotes in #3) required that. At least for me removing platform invocation reduced the time by half.

dbenham wrote:
19 May 2019 19:33
The first time I launch PowerShell within a given cmd.exe process, it is always S... L... O.... W.......
Thereafter it is relatively fast.
I'm facing the same symptoms. I guess some kind of caching is in place. However, the way you write it makes me assume that it is even slower than usual. Try to speed it up a litte by precompiling and installing assemblies. I found a little powershell script in the internet and wrapped it into a JScript hybrid to invoke the UAC prompt

Code: Select all

@if (@a)==(@b) @end /*
@echo off &setlocal EnableExtensions DisableDelayedExpansion
>nul 2>&1 net.exe session || (
  cscript.exe //nologo //e:jscript "%~fs0"
  exit /b
)

powershell.exe -nop -ep Bypass -c ^"^
$Env:Path=[Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory();^
[AppDomain]::CurrentDomain.GetAssemblies() ^| %% {^
  if (-not $_.Location) {continue};^
  Write-Host -ForegroundColor Cyan ('Compiling ' + (Split-Path -Leaf $_.Location));^
  ngen.exe install $_.Location;^
  '';^
}^"
pause

goto :eof */ WScript.CreateObject('Shell.Application').ShellExecute('cmd.exe', ' /c ""' + WScript.ScriptFullName + '""', '', 'runas', 1);
I run it every time that a .NET update came in. Most of the times the script finds a library that has to be newly compiled, and after that powershell returns to execute in reasonable speed. Just give it a go. Not sure if it will help in your case though.

dbenham wrote:
19 May 2019 19:33
I opted to allow /VT without /H or /HU. Unlikely, but it is possible a source file could already have escape sequences, or they could be introduced by a find/replace without using /H or /HU.
I didn't think about that. Good point :!:

Steffen

Post Reply