ANSI color Set Graphics Rendition прерывает среднюю партию и работает после ее продолжения

У меня есть пакет, у которого есть подраздел, который выполняет итерации по строкам файла для EXE, чтобы попробовать запустить, а затем пакет сортирует EXE на основе их кодов выхода.

По какой-то причине ANSI SGR, похоже, сломает или повторит буквенный текст после установки графического исполнения предыдущего, вместо повторного рендеринга.

Я вернулся к повторной ссылке на этот question и исходную документацию, но я не уверен, почему эта конкретная область моих партий изменяет ANSI окраска внутри консоли после повторения первой строки.

Я поменял свой инструмент только "Блокнотом", который вы можете закрыть вручную для нулевого выхода или использовать панель управления, чтобы завершить процесс, чтобы получить ненулевой выход.

Содержимое test_map.log не должно иметь большого значения, поскольку вы фактически используете только Блокнот и отправляете ему некоторые аргументы. Это мои настройки:

C:\temp\qt_selftest.exe
C:\temp\sub_test.exe
C:\temp\cmd_module_test.exe
C:\temp\failing_qt_test.exe
C:\temp\passing_qt_test.exe
C:\temp\random_qt_test.exe
C:\temp\fail_module.exe
C:\temp\pass_module.exe

И как вы можете видеть на скриншоте, линии обрабатываются буквально. В пределах фактической партии, из которой я вытащил это, он снова возвращается к работе... но внутри этого блока и только в этом блоке он сломан.

введите описание изображения здесь

Любая идея, где я мог бы испортить это?

Я не могу передать код напрямую из-за преобразования ESC-последовательностей, поэтому вот суть: https://gist.github.com/the-nose-knows/1bebce2719e020188c6307cff736f951

Если вам нужно повторно добавить их перед [, используйте альт-код 027, как alt 0 2 7

Ответ 1

Как сказал Эриксон, это можно решить, установив режим виртуального терминала. Если вам нужен только цвет PowerShell, вы можете добавить переключатель /A к вашему вызову в CMD.exe, иначе вам понадобится небольшой процесс, который обрабатывает такой тип, как прокладка, но тот, который также гарантирует VTM включен. Это не совсем плохо, поскольку этот уровень абстракции может пригодиться для будущих случаев использования и ошибок.

Единственной "странной" частью этого фрагмента будет мое использование rel-path. Этот фрагмент - это прокладка процесса из подкаталога для запуска пакетной прокладки из одного каталога.

Важными частями кода являются заголовки для включения и включения VTM для StdOut после получения дескриптора консоли.

#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;
}