Ahmed AE Ответов: 2

Последний результат команды CMD не может быть пойман?


Я пытаюсь выполнить команду в командной строке. Эта команда отправляется с языка c++. Если я пытаюсь выполнить 3 команды, то выполняется только 2, а третья не возвращается в c++.
Вот что я пытаюсь выполнить:
wmic diskdrive get serialnumber& wmic cpu get ProcessorId& wmic os get SerialNumber& echo %username%


Вот фрагмент кода перехвата возврата из CMD my prog:
cmd.append("2>&1");

    std::string data;
    FILE * stream;
    const int char_length= 256;
    char buffer[char_length];

    stream = popen(cmd.c_str(), "r");
    if (stream)
    {
        while (!feof(stream))
        if (fgets(buffer, char_length, stream) != NULL)
            data.append(buffer);
        pclose(stream);
     }
    return data;


Возвращаемый код содержит информацию о первой команде 3. Я думал, что есть какая-то проблема с последней командой, но при попытке поменять команду последняя команда также не была поймана программой.

Что я уже пробовал:

Я обошел проблему, сделав последнюю команду бесполезной (что мне не нужно), я сделал это:
echo

std::string cmd("wmic diskdrive get serialnumber& wmic cpu get ProcessorId& echo %username%& wmic os get SerialNumber& echo");


я думаю, что для этого должно быть решение, заранее спасибо за помощь

2 Ответов

Рейтинг:
16

Jochen Arndt

Линия, которая создает проблему, является

cmd.append("2>&1");
Вы забыли вставить пробел перед перенаправлением вывода:
cmd.append(" 2>&1");

Без пробела последняя команда такова
echo %username%2
и вывод перенаправляется на stdout Но это не работает, потому что вход уже от stdout так что перенаправление завершается неудачей с сообщением об ошибке на stderr который теперь не улавливается вашим кодом.

Попробуйте сделать это в командной строке, чтобы увидеть сообщение об ошибке:
echo %username%2>&1
The handle could not be duplicated during redirection of handle 1.


Ahmed AE

Спасибо, у меня есть еще 2 вопроса, пожалуйста.
1. во время выполнения этого кода CMD мигает, есть ли какой-нибудь способ остановить его мигание?
2. Как поймать stderr, как вы сказали?

Jochen Arndt

См. решение 1.

В противном случае вам придется использовать CreateProcess(), установить член wShowWindow структуры STARTUPINFO в SW_HIDE и добавить STARTF_USESHOWWINDOW в член dwFlags. Или используйте флаг CREATE_NO_WINDOW. Чтобы прочитать выходные данные, вы должны создать канал, как описано в разделе https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=против 85).aspx.

Jochen Arndt

Извините, забыл о втором вопросе.

поток stderr это поймал, когда, используя исправленный код. Вот что делает "2>&1" :
Он перенаправляет stderr (2) в stdout(1), так что оба выходных потока считываются вашим кодом. Но в неправильной команде "2" - это просто символ (напечатанный с помощью оператора echo), так что перенаправление не работает.

Рейтинг:
0

Dave Kreskowiak

Почему вы вообще стреляете в wmic, чтобы запустить запросы? Выполняйте запросы непосредственно сами. Примеры приложений WMI C++ (Windows)[^]