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

查看:12
本文介绍了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 用法.此代码段是来自子目录的进程填充程序,用于从一个目录运行批处理填充程序.

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

#include #include <字符串>#include <向量>#include <迭代器>#include #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);如果 (path_white_space_query != std::string::npos){返回真;}返回假;}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);//只是将发送到此 shim 的参数转发到已知位置的批处理中,//确保空格参数在转发时保留其引号.//CMD.exe 需要正确的引用处理,否则调用会被破坏.std::string str = "C:\Windows\System32\cmd.exe/C """ + path + "\..\app_shim.bat"";std::vector参数;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());关闭句柄(标准输出句柄);返回退出代码;}

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天全站免登陆