Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Resager от Апрель 03, 2013, 13:05



Название: Отловить вывод в стандартный поток
Отправлено: Resager от Апрель 03, 2013, 13:05
Стоит передо мной задача отловить вывод приложения в стандартный поток. Запускаю её в консоли (CMD). Информация выводится. Пытаюсь отловить в Qt, не получается. Причем ping и ipconfig норм отлавливаю, а вот другие приложения, не стандартные виндозные или самописные, то программно не получается вывод получить. Даже по совету пробовал использовать "cmd /C команда", все равно не идет. (в примере ниже одна строка из проверенного метода за комментирована "//myprocess->start..." Помогите пожалуйста.

.H
Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "ui_mainwindow.h"
#include <QProcess>

class MainWindow : public QMainWindow, private Ui::MainWindow
{
    Q_OBJECT
   
public:
    explicit MainWindow(QWidget *parent = 0);
    QProcess *myprocess;
private slots:
    void on_pushButton_clicked();
    void outExec();
    void finishExec ( int exitCode, QProcess::ExitStatus exitStatus );
};

#endif // MAINWINDOW_H

.CPP
Код:
#include "mainwindow.h"
#include <QDebug>
#include <QDir>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    setupUi(this);
}

void MainWindow::on_pushButton_clicked()
{
    QString programm =  lineEdit->text();
    myprocess = new QProcess(this);
    myprocess->setObjectName(programm);
    //myprocess->start(QString("exec\\" + programm).toAscii());
    myprocess->start(QString("cmd /C " + QDir::currentPath() + "/exec/" + programm).toAscii());
    qDebug() << "RUN " << QString("cmd /C " + QDir::currentPath() + "/exec/" + programm).toAscii();
    connect(myprocess, SIGNAL(readyReadStandardOutput ()), this, SLOT(outExec()));
    connect(myprocess, SIGNAL(finished (int,QProcess::ExitStatus)), this, SLOT(finishExec(int,QProcess::ExitStatus)));
}

void MainWindow::outExec()
{
    QString out = myprocess->readAllStandardOutput();
    qDebug() << "__" << out;
    plainTextEdit->appendPlainText(QString(out));
}

void MainWindow::finishExec ( int exitCode, QProcess::ExitStatus exitStatus )
{
    QString out = myprocess->readAllStandardOutput();
    qDebug() << out;
    plainTextEdit->appendPlainText(QString(out));
}

Запускал скопированный в подпапку exec проекта curl.exe и стандартный (но скопирован)  attrib.exe и самописный drivespacefree.exe (выводит число в консоль)
+ прикрепил проект в архиве.


Название: Re: Отловить вывод в стандартный поток
Отправлено: carrygun от Апрель 03, 2013, 13:26
Первый мой совет я смотрю не помог, тогда второй: внимательно почитай про cmd.
Код:
p->start(QString("cmd /C \"%1\"").arg(QDir::currentPath()+"/attrib.exe"));
Вот пример запуска по указанному пути.


Название: Re: Отловить вывод в стандартный поток
Отправлено: Resager от Апрель 03, 2013, 13:36
Ну работает для скопированной attrib.exe (консольной проги), для графической (ну точнее "не консольной", но без как такового гуя (и не QT) проги, все равно не работает.


Название: Re: Отловить вывод в стандартный поток
Отправлено: mutineer от Апрель 03, 2013, 13:39
Попробуй кроме StandardOutput читать еще и StandardError


Название: Re: Отловить вывод в стандартный поток
Отправлено: Resager от Апрель 03, 2013, 13:53
Увы, но нет. Добавил

Код:
connect(myprocess, SIGNAL(readyReadStandardError ()), this, SLOT(outExec()));
И в обоих функциях
QTextCodec *codec = QTextCodec::codecForName("CP866");  //Windows-1251 CP1251 KOI8-R
    out += codec->toUnicode(myprocess->readAllStandardError());

Вывело только когда неправильный путь задал, а так тоже пусто

Может неконсольные проги куда-нибудь ещё отсылают? Что интересно, CMD все равно выводит (когда  запускаешь руками).


Название: Re: Отловить вывод в стандартный поток
Отправлено: Patrin Andrey от Апрель 03, 2013, 16:01
Попробуй подождать, чтобы эта программа побольше вывода сделала. Вполне возможно что вывод ты получишь не построчно а 1 куском с кучей строчек при достижении определённого порога.


Название: Re: Отловить вывод в стандартный поток
Отправлено: Resager от Апрель 03, 2013, 17:01
Попробуй подождать, чтобы эта программа побольше вывода сделала. Вполне возможно что вывод ты получишь не построчно а 1 куском с кучей строчек при достижении определённого порога.
Программа выполняется очень быстро, выводит всего одну строку и завершается. Ничего не получаешь.

Может просто это не стандартный поток вывода? Как тогда использовать нестандартный?

Нашел один костыль - использовать лог файл, работает ещё для пару примеров, но опять же не работает для вывода из неконсольной.

В месте вызова:
Код:
myprocess->setStandardOutputFile(programm + ".log",QIODevice::WriteOnly);
            myprocess->setObjectName(programm);

В слоте на выход программы:
Код:
QString name = currentProcess->objectName();
        QFile file;
        file.setFileName(name + ".log");
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            return;
        }
        else
        {
            QString logFile;
            QTextStream in(&file);
            while (!in.atEnd())
            {
                logFile += in.readLine();
            }
            if (logFile!="")
                textEdit->setText(logFile);
            else
                return;
        }