ANSI 颜色集图形再现在批处理中中断并在继续后工作 [英] ANSI color Set Graphics Rendition breaking mid-batch and working after it proceeds

查看:13
本文介绍了ANSI 颜色集图形再现在批处理中中断并在继续后工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个批处理,它有一个子部分,它遍历文件的行以供 EXE 尝试运行,然后批处理根据 EXE 的退出代码对它们进行排序.

由于某种原因,ANSI SGR 似乎在设置前一个的图形呈现而不是重新呈现它之后打破或回显文字文本.

我回去重新引用这个

知道我可能在哪里搞砸了吗?

由于 ESC 序列被转换,我无法直接共享代码,所以这里是要点:https://gist.github.com/the-nose-knows/1bebce2719e020188c6307cff736f951

如果您需要在[之前重新添加它们,请使用027的alt-code,如alt 0 2 7

解决方案

正如 erykson 所说,这可以通过确保启用虚拟终端模式来解决.如果您关心 PowerShell 的颜色,则可以将 /A 开关添加到对 CMD.exe 的调用中,否则您将需要一个处理此问题的小进程有点像垫片,但也可以确保启用 VTM.这完全不是一件坏事,因为这个抽象层可以在未来的用例和错误中派上用场.

这个片段中唯一奇怪"的部分是我的 rel-path 用法.此代码段是来自子目录的进程 shim,用于从上一个目录运行批处理 shim.

代码的重要部分是在获取控制台句柄后要包含并为 StdOut 启用 VTM 的标头.

#include <iostream>#include <字符串>#include <向量>#include <迭代器>#include <Windows.h>#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004#万一bool uses_whitespace(std::string test_string){size_t path_white_space_query = test_string.find(' ', 0);if (path_white_space_query != std::string::npos){返回真;}返回假;}int main(int argc, char* argv[]){std::string this_app_path = std::string(argv[0]);自动它 = this_app_path.find_last_of("\", std::string::npos);std::string path(this_app_path, 0, it);//只是将发送到此 shim 的 args 转发到已知位置的批次,//确保空白参数在转发时保留其引号.//CMD.exe 将需要正确的引用处理,否则调用将被破坏.std::string str = "C:\Windows\System32\cmd.exe/C """ + 路径 + "\..\app_shim.bat"";标准::向量<标准::字符串>参数;std::copy(argv + 1, argv + argc, std::back_inserter(args));for (auto const& arg : args){if (uses_whitespace(arg)){str += (" "" + arg + """);}别的{str += (" " + arg);}}//CMD 调用结束最终包装报价str += """;处理 stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);双字模式 = 0;GetConsoleMode(stdOutHandle, &mode);SetConsoleMode(stdOutHandle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);int exit_code = system(str.c_str());关闭句柄(stdOutHandle);返回退出代码;}

I've got a batch that has a sub-section which iterates through lines of a file for EXEs to try running, and then the batch sorts the EXEs based on their exit codes.

For some reason, the ANSI SGR seems to break or echo the literal text after setting the graphics rendition of the previous one instead of re-rendering it.

I went back to re-reference this question and the original documentation, but I'm not sure why this specific area of my batches is mangling the ANSI coloration inside the console after the first line is echoed.

I swapped my tool with just Notepad, which you can manually close for a zero-exit, or use the Control Panel to end the process to get a non-zero exit.

The contents of test_map.log shouldn't matter too much since you're actually using just Notepad and sending it some args. This is what mine are set to:

C:	empqt_selftest.exe
C:	empsub_test.exe
C:	empcmd_module_test.exe
C:	empfailing_qt_test.exe
C:	emppassing_qt_test.exe
C:	emp
andom_qt_test.exe
C:	empfail_module.exe
C:	emppass_module.exe

And as you can see from the screenshot, the lines are being treated literally. Within the actual batch that I pulled this from, it does go back to working again... but within that block and only in that block, it's broken.

Any idea where I might be messing this up?

I can't share the code directly due to ESC sequences being converted, so here is the gist: https://gist.github.com/the-nose-knows/1bebce2719e020188c6307cff736f951

If you need to re-add them before the [, use the alt-code of 027, as alt 0 2 7

解决方案

As erykson said, this can be solved by making sure Virtual Terminal Mode is enabled. If you only care about PowerShell's color, you can add the /A switch to your call to CMD.exe, otherwise you're going to want a small process that handles this kind of like a shim, but one that also makes sure VTM is enabled. This isn't wholly a bad thing, as this abstraction layer could come in handy for future use cases and bugs.

The only "weird" part of this snippet would be my rel-path usage. This snippet is a process shim from a sub-directory to run a batch shim from up one directory.

The important parts of the code are the headers to include and enabling VTM for StdOut after getting the console handle.

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <Windows.h>

#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif

bool uses_whitespace(std::string test_string)
{
    size_t path_white_space_query = test_string.find(' ', 0);

    if (path_white_space_query != std::string::npos)
    {
        return true;
    }

    return false;
}

int main(int argc, char* argv[])
{
    std::string this_app_path = std::string(argv[0]);

    auto it = this_app_path.find_last_of("\", std::string::npos);

    std::string path(this_app_path, 0, it);

    // Just forwarding the args that were sent to this shim to a batch in a known location,
    // making sure whitespace arguments keep their quotes when forwarded.

    // CMD.exe will need proper quote-handling, or the call will get mangled.
    std::string str = "C:\Windows\System32\cmd.exe /C """ + path + "\..\app_shim.bat"";
    std::vector<std::string> args;
    std::copy(argv + 1, argv + argc, std::back_inserter(args));

    for (auto const& arg : args)
    {
        if (uses_whitespace(arg))
        {
            str += (" "" + arg + """);
        }
        else
        {
            str += (" " + arg);
        }
    }

    // end-of-CMD-call final wrapping quote
    str += """;

    HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);

    DWORD mode = 0;
    GetConsoleMode(stdOutHandle, &mode);
    SetConsoleMode(stdOutHandle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);

    int exit_code = system(str.c_str());

    CloseHandle(stdOutHandle);

    return exit_code;
}

这篇关于ANSI 颜色集图形再现在批处理中中断并在继续后工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆