QProcess problems, output of process

后端 未结 2 1023
别跟我提以往
别跟我提以往 2021-01-06 05:48

I am trying to figure out the use of QProcess. I looked at Qt doc with no luck.
http://doc.qt.io/qt-4.8/qprocess.html

EXAMPLES OF PROBLEM.

相关标签:
2条回答
  • 2021-01-06 05:59

    eI see one big problem. Under windows you issue a commend pressing the Enter key. Writing

    cmd.write("command");
    cmd.write("\n");
    


    just isn't enough you have to write

    cmd.write("command");
    cmd.write("\n\r");
    

    Notice the trailing \r. Try this, it should work better, and by better I mean 7zip. I don't know if you'll get ipconfig to work properly.

    Good luck and best regards
    D

    EDIT Here is a working solution:

    
    #include <QtCore/QCoreApplication>
    #include <QtCore/QProcess>
    #include <QtCore/QString>
    #include <QtCore/QTextStream>
    
    // Not clean, but fast
    QProcess *g_process = NULL;
    
    // Needed as a signal catcher
    class ProcOut : public QObject
    {
      Q_OBJECT
    public:
      ProcOut (QObject *parent = NULL);
      virtual ~ProcOut() {};
    
    public slots:
      void readyRead();
      void finished();
    };
    
    ProcOut::ProcOut (QObject *parent /* = NULL */):
    QObject(parent)
    {}
    
    void
    ProcOut::readyRead()
    {
      if (!g_process)
        return;
    
      QTextStream out(stdout);
      out << g_process->readAllStandardOutput() << endl;
    }
    
    void
    ProcOut::finished()
    {
      QCoreApplication::exit (0);
    }
    
    int main (int argc, char **argv)
    {
      QCoreApplication *app = new QCoreApplication (argc, argv);
    
      ProcOut *procOut = new ProcOut();
      g_process        = new QProcess();
    
      QObject::connect (g_process, SIGNAL(readyReadStandardOutput()),
        procOut, SLOT(readyRead()));
      QObject::connect (g_process, SIGNAL(finished (int, QProcess::ExitStatus)),
        procOut, SLOT(finished()));
    
      g_process->start (QLatin1String ("cmd"));
      g_process->waitForStarted();
    
      g_process->write ("ipconfig\n\r");
    
      // Or cmd won't quit
      g_process->write ("exit\n\r");
    
      int result = app->exec();
    
      // Allright, process finished.
      delete procOut;
      procOut = NULL;
    
      delete g_process;
      g_process = NULL;
    
      delete app;
      app = NULL;
    
      // Lets us see the results
      system ("pause");
    
      return result;
    }
    
    #include "main.moc"
    

    Hope that helps. It worked everytime on my machine.

    0 讨论(0)
  • 2021-01-06 06:14

    Even though Dariusz Scharsig already provided a solution to the problem, I would like to point out what I believe to be the actual problem(s) which can be solved using the signal slot mechanism.

    Problem 1. The condition in your while loop is based on bool QProcess::atEnd () const which is according to QProcess Documentation states:

    Reimplemented from QIODevice::atEnd().

    Returns true if the process is not running, and no more data is available for reading; otherwise returns false.

    But if you looking the documentation for QIODevice::atEnd(), it states:

    Returns true if the current read and write position is at the end of the device (i.e. there is no more data available for reading on the device); otherwise returns false.

    For some devices, atEnd() can return true even though there is more data to read. This special case only applies to devices that generate data in direct response to you calling read() (e.g., /dev or /proc files on Unix and Mac OS X, or console input / stdin on all platforms).

    Solution 1. Change the while loop condition to check the state of your process: while(cmd2.state()!=QProcess::NotRunning){.

    Problem 2. You use cmd2.waitForReadyRead(); outside of the loop. Perhaps some data is ready for reading now and when you finished reading, some more gets made available:

    • you read the commands you just wrote : ipconfig\n
    • ipconfig takes some time to start up and send text to the console. But by then you have already exited your loop because atEnd() gave true even though your process is still running.

    Solution 2. place the waitForReadyRead() inside your loop.

    Consequence 2. waitForReadyRead() will tell you when there is data available, which could be more than one Line, so you should consequently also change the cmd2.ReadLine() to cmd2.ReadAll().

    Problem 3. As documented in QProcess::closeWriteChannel()

    Closing the write channel is necessary for programs that read input data until the channel has been closed.

    Solution 3. One of the following options should work when finished writing your inputs

    • End the process: cmd2.write("exit\n");
    • close the Writechannel: cmd2.closeWriteChannel();

    Working code:

    #include <QtCore/QCoreApplication>
    #include <QTextStream>
    #include <QByteArray>
    #include <QString>
    #include <QProcess>    
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        QTextStream qout(stdout);
        QByteArray result;
        QProcess cmd2;
    
        cmd2.setReadChannel(QProcess::StandardOutput);
        cmd2.setProcessChannelMode(QProcess::MergedChannels);
        cmd2.start("cmd");
        if (!cmd2.waitForStarted()){
            qout << "Error: Could not start!" << endl;
            return 0;
        }
        cmd2.write("ipconfig\n");
        cmd2.closeWriteChannel();   //done Writing
    
        while(cmd2.state()!=QProcess::NotRunning){
            cmd2.waitForReadyRead();
            result = cmd2.readAll();
            qout << result;
        }
        qout << endl << "---end----" << endl;
        return a.exec();
    }
    

    I wrote this answer just to explain the way I understand your problem and found a solution but would like to emphasize that the Preferable Solution is to use the Signal/Slot Mechanism as presented by Dariusz.

    0 讨论(0)
提交回复
热议问题