Не могу получить вывод процесса в строку QT

Мне нужно считать вывод процесса QProcess в QString

QString program = "cmd", output;
    command = "cd /d ";
    command += QString::fromLocal8Bit(dir); //здесь хранится путь до папки, в которой должна исполняться команда
    command += " & pip list";
    qDebug() << command;
    arg << "/C" << command;
    QProcess *Process2 = new QProcess(this);
    Process2->start(program, arg);
    connect(Process2, &QProcess::readyReadStandardOutput, [&] {
       QString output(Process2->readAll());
    });
    qDebug() << output;

Я проверил - команда, которая хранится в command - работает, но в строке qDebug() << output; я получаю значение "". С кодировкой всё в порядке (команда сама по себе выводится и её можно скопировать и вставить в cmd - она сработает). Как мне получить в строку output вывод этого процесса?


Ответы (2 шт):

Автор решения: goldstar_labs

В вашем варианте вы используте асинхронное апи, поэтому ваша лямбда вызовется непонятно в какое время и нельзя сразу после старта печатать вывод, надо делать это в самой лямбде

QString program = "cmd", output;

command = "cd /d ";
command += QString::fromLocal8Bit(dir); //здесь хранится путь до папки, в которой должна исполняться команда
command += " & pip list";

qDebug() << command;

arg << "/C" << command;

QProcess *Process2 = new QProcess(this);

// Лямбда выражение будет выполнено после вызова Process2->start
connect(Process2, &QProcess::readyReadStandardOutput, [&] {
    output = QString::FromLocal8Bit(Process2->readAll());
    qDebug() << output;
});

Process2->start(program, arg);

Вариант 2 - использовать синхронное апи (https://doc.qt.io/qt-5/qprocess.html#synchronous-process-api)

QString program = "cmd", output;

command = "cd /d ";
command += QString::fromLocal8Bit(dir); //здесь хранится путь до папки, в которой должна исполняться команда
command += " & pip list";

qDebug() << command;

arg << "/C" << command;

QProcess *Process2 = new QProcess(this);

connect(Process2, &QProcess::readyReadStandardOutput, [&] {
    output = QString::FromLocal8Bit(Process2->readAll());
});

Process2->start(program, arg);

Process2->waitForFinished(); // Ждем завершения роцесса

qDebug() << output; // Во время waitForFinished, будет совершен асинхронный вызов лямбды, которая сохранит вывод в переменную и её можно использовать уже после завершения процесса
→ Ссылка
Автор решения: Sergey Tatarincev
  1. зачем в лямбде повторное объявление переменной? почитайте про область видимости переменных. У вас получается две переменных с одним именем.
  2. В лямбде вы каждый раз переписываете значение, но данные будут поступать постепенно и у вас на руках останется только последняя порция.
  3. Работа сигналов-слотов АСИНХРОННАЯ. И ожидать в последней строке готового вывода бесполезно - qDebug() << output; отработает еще до того как в output появятся данные

Вот

QString program = "ping 127.0.0.1";                          
QString* output = new QString(); // лямбда будет с доступом к переменным по значению, поэтому тут у нас будет указатель

QProcess *Process = new QProcess(this);                      
Process->start(program);                                     

connect(Process, &QProcess::readyReadStandardOutput, [=] {   
        output->append(Process->readAll());   // НЕ ПЕРЕПИСЫВАЕМ а дописываем               
});                                                          
Process->waitForFinished(); // ЖДЕМ ЗАВЕРШЕНИЯ процесса
qDebug()<<output;                                            

UPD: Еще как вариант, если все равно будет синхронная работа, обойтись без лямбд и сигналов:

QString program = "ping 127.0.0.1";

QProcess *Process = new QProcess(this);
Process->start(program);    
Process->waitForFinished();
QString output = Process->readAllStandardOutput();
qDebug()<<output;

PS: сдается мне что вашу программу по итогу напишет сообщество SO. Я думал уж с этим то справитесь, тем более что на подобный вопрос уже отвечалось

→ Ссылка