如何在 Windows 10 上将 ANSI 转义序列与 CSCRIPT 一起使用?

How to use ANSI escape sequences with CSCRIPT on Windows 10?

我正在尝试通过 CSCRIPT (JScript) 使用 Windows 10 控制台中可用的新 VT100 ANSI 转义序列功能。但是我无法让它工作。

这是一个非常简单的 JScript 脚本:

test.js

WScript.Echo('\x1B[7mReverse\x1B[0m Normal');
WScript.stdout.WriteLine('\x1B[7mReverse\x1B[0m Normal');

我做了很多测试,CSCRIPT 输出的转义序列在直接写到屏幕上时是无能为力的,只有先写入文件然后再键入,或者用 FOR /F 捕获才能工作回声。

我有两个问题:

1) 为什么从 CSCRIPT 直接写入控制台不起作用?
2) 如何让直接写入工作?

我想在我的 JREPL.BAT regular expression find/replace utility (hence the 标签中添加文本突出显示),但如果它需要临时文件 and/or FOR /F.

,我将不会实现该功能

第 2 部分的更新答案:如何使其在 CSCRIPT 中工作

我终于在 this SuperUser answer 找到了一种在 CSCRIPT 中启用 VT-100 序列的机制。我从答案中复制了相关文本并发布在下面。

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.

[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.

请注意,此更改仅影响新启动的控制台 windows - 它不会为现有控制台启用 VT-100 windows。


this thread 中,DosTips 用户 aGerman 发现您可以通过从脚本中异步启动 PowerShell 来启用转义序列。 PowerShell 将输出配置为支持转义序列,即使在 PowerShell 退出后,只要您的 CSCRIPT 进程保持活动状态,该支持仍然存在。

例如,这里有一些 JScript 代码可以启用序列

var ps = WScript.CreateObject("WScript.Shell").Exec("powershell.exe -nop -ep Bypass -c \"exit\"");
while (ps.Status == 0) WScript.Sleep(50);


我对第 1 部分的原始回答:为什么它在 CSCRIPT 中不起作用

好的,我想我有一个可行的理论来解释为什么它不起作用。我相信必须有一些低级别 way/call/function/method (无论如何)将 stdout 传递到只有少数内部命令知道的控制台。我的依据是 FINDSTR 也无法向控制台发送有效的转义序列,如下所示:

我已经证明了 TYPE 和 ECHO 都有效。我还验证了 SET /P 有效(未显示)。所以我怀疑 cmd.exe 被修改为支持新的 Windows 10 控制台功能。

我希望看到一些描述将转义序列发送到控制台所需机制的 MS 文档。

MS documentation 状态

The following terminal sequences are intercepted by the console host when written into the output stream if the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag is set on the screen buffer handle using the SetConsoleMode flag. You can use GetConsoleMode and SetConsoleMode flags to configure this behavior.

所以,为了测试,我写了一个简单的 C 程序来更改控制台模式,然后充当管道或启动另一个进程并等待(抱歉,只是测试代码)。

#define _WIN32_WINNT   0x0500
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004

int _tmain(int argc, TCHAR *argv[]){

    // Console handlers
    DWORD dwOldMode, dwMode ;
    HANDLE hStdout;

    // Pipe read buffer
    int c;

    // Spawn process variables
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    // Retrieve standard output handle
    hStdout = GetStdHandle( STD_OUTPUT_HANDLE );
    if (! GetConsoleMode( hStdout, &dwOldMode ) ) {
        return 1;
    }

    // Change standard output handle
    dwMode = dwOldMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    if (! SetConsoleMode( hStdout, dwMode ) ){
        CloseHandle( hStdout );
        return 2;
    }

    if( argc < 2 ) {
        // If there is not an argument, read stdin / write stdout 
        while ( EOF != (c = getchar()) ) putchar( c );    
    } else {
        // Argument is present, create a process and wait for it to end
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
        if( !CreateProcess(NULL, argv[1], NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi )){
            printf( "CreateProcess failed (%d).\n", GetLastError() );
            return 3;
        }
        WaitForSingleObject( pi.hProcess, INFINITE );
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );    
    }

    // Restore old console mode
    SetConsoleMode( hStdout, dwOldMode );
    CloseHandle( hStdout );

    return 0;
};

使用 mingw/gcc 编译为 run.exe。结果是

现在,处理 cscriptfindstr 的输出并解释转义序列。

此外,如果我 运行 cmd.exe 本身 运行 不是 运行 单独的程序,而是

因为我没有更改 findstr.execscript.execmd.exe 的代码,所以只有他们工作的环境 似乎

  • 既不cscript也不findstr configure/change控制台缓冲区配置

  • 一些内部 cmd 命令更改缓冲区配置(我忘记将其包含在捕获中,但 copy test.txt conprompt 也可以)或者,作为你点,他们用不同的输出方式

  • 写入标准输出流的应用程序的唯一要求是正确配置控制台输出缓冲模式。

不,我不知道如何从纯批处理中启用它。