Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QProcess::readAll and QProcess::readAllStandardOutput both return an empty string after QProcess::write() is run
QtWS25 Last Chance

QProcess::readAll and QProcess::readAllStandardOutput both return an empty string after QProcess::write() is run

Scheduled Pinned Locked Moved Solved General and Desktop
qprocessreadlinestdioqt 5.7qtcreator
15 Posts 8 Posters 18.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • CybeXC Offline
    CybeXC Offline
    CybeX
    wrote on last edited by
    #1

    Hi all

    note: this might become confusing, please bare with me!

    To get a basic sense of what I want to do:

    QProcess runs a command by

    QProcess::start("sh -c \"cd /tmp/tempdir ; ./my_script --option file.txt ; echo $?\" ")
    

    The script expects input from the user (a password), QProcess::readAll() confirms the script's input request. The input is given by QProcess::write().

    Here I get lost! -> No output is received. from readAll() and readAllStandardOutput(), both are empty.

    I need the output: particularly the echo $? for later processing, but don't get anything since readAll() and readAllStandardOutput() returns empty strings

    To me there are several possible issues to cause this, maybe more than one:

    • The script does not receive this input
    • The script receives the input, but expects a "return key press"
    • The script receives the input, QProcess::write automatically does a "return key press", the script continues and finishes but QProcess does not read this output

    The Code:

    // please ignore the messiness of the code, a placed a number of debugs just to see the code response.

    cmd = "cd /tmp/tempdir ; ./my_script --option file.txt ; echo $?" (without quotes)
    input => required input for script

    QString gen_serv::runCommand(QString cmd, QString input){
        Process *p = new QProcess(parent);
        p->setProcessChannelMode(QProcess::MergedChannels);
        //    p->start("sh ", QStringList() << " -c " << cmd);
        QString c = QString("sh -c \"" + cmd + "\" ");
        p->start(c);                                 <---- ACTUAL COMMAND : sh -c "cd /tmp/tempdir ; ./my_script --option file.txt ; echo $?"
        if (p->waitForStarted()) {
            if (!p->waitForReadyRead()) {
                qDebug(log_lib_gen_serv) << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
            }
            if (!p->waitForFinished(1000)) {
                qDebug() << p->readAll();
                qDebug() << p->readAllStandardOutput();
    			//p->write(input.toLatin1());
                p->write(QString(input + QString("\n")).toLatin1());           <--- added this "\n" incase the process/console was waiting for a return press, thus the /n should satisfy the return requirement
                qDebug() << p->readAll();
                qDebug() << p->readAllStandardOutput();
                if (!p->waitForFinished()) {
                    qDebug() << p->readAll();
                    qDebug() << p->readAllStandardOutput();
                    qDebug(log_lib_gen_serv) << "waitForFinished() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
                }
                qDebug() << p->readAll();
                qDebug() << p->readAllStandardOutput();
            }
            QString s = QString(p->readAll() + p->readAllStandardOutput());
            return s;
        }
        else{
            qDebug(log_lib_gen_serv) << "waitForStarted() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
        }
        p->waitForFinished();
        p->kill();
        return QString();
    }
    

    Please note:

    The script is long and complicated, however it returns a message "done" if successfully executed and an exit code for each case.
    Thus the echo $? should capture and return this for processing i.e. return s

    I hope this makes sense, any suggestions how I can attempt to solve this issue?

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      Did u start event loop before waiting for the response to come from your external processes?

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      CybeXC 1 Reply Last reply
      3
      • dheerendraD dheerendra

        Did u start event loop before waiting for the response to come from your external processes?

        CybeXC Offline
        CybeXC Offline
        CybeX
        wrote on last edited by
        #3

        @dheerendra hi, thanks for the response.

        Event loop? This is all the code related to the process.

        If you could provide an example on a possible event loop, I believe it would be of much use

        Thanks!

        jsulmJ 1 Reply Last reply
        0
        • CybeXC CybeX

          @dheerendra hi, thanks for the response.

          Event loop? This is all the code related to the process.

          If you could provide an example on a possible event loop, I believe it would be of much use

          Thanks!

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @CybeX After writing you should first wait for readyRead.
          Instead you read just after writing:

          p->write(QString(input + QString("\n")).toLatin1()); 
          qDebug() << p->readAll();
          qDebug() << p->readAllStandardOutput();
          

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by VRonin
            #5

            why, oh why, did The Lord invent the synchronous API?! it's an aberration!

            QString gen_serv::runCommand(const QString& cmd, const QString& input){
            QString result;
            QEventLoop looper;
            Process *p = new QProcess(&looper);
            p->setProcessChannelMode(QProcess::MergedChannels);
            QObject::connect(p,&QProcess::finished,&looper,&QEventLoop::quit);
            QObject::connect(p,&QProcess::errorOccurred,[&result]()->void{qDebug("Error in Process"); result.clear();});
            QObject::connect(p,&QProcess::errorOccurred,&looper,&QEventLoop::quit);
            QObject::connect(p,&QProcess::started,[p,&input]()->void{p->write((input +'\n').toLatin1());});
            QObject::connect(p,&QProcess::readyReadStandardOutput,[p,&result]()->void{result+=p->readAllStandardOutput();});
            const QString c = QString("sh -c \"" + cmd + "\" ");
            p->start(c);
            looper.exec();
            return result;
            }
            

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            CybeXC 1 Reply Last reply
            5
            • VRoninV VRonin

              why, oh why, did The Lord invent the synchronous API?! it's an aberration!

              QString gen_serv::runCommand(const QString& cmd, const QString& input){
              QString result;
              QEventLoop looper;
              Process *p = new QProcess(&looper);
              p->setProcessChannelMode(QProcess::MergedChannels);
              QObject::connect(p,&QProcess::finished,&looper,&QEventLoop::quit);
              QObject::connect(p,&QProcess::errorOccurred,[&result]()->void{qDebug("Error in Process"); result.clear();});
              QObject::connect(p,&QProcess::errorOccurred,&looper,&QEventLoop::quit);
              QObject::connect(p,&QProcess::started,[p,&input]()->void{p->write((input +'\n').toLatin1());});
              QObject::connect(p,&QProcess::readyReadStandardOutput,[p,&result]()->void{result+=p->readAllStandardOutput();});
              const QString c = QString("sh -c \"" + cmd + "\" ");
              p->start(c);
              looper.exec();
              return result;
              }
              
              CybeXC Offline
              CybeXC Offline
              CybeX
              wrote on last edited by
              #6

              @VRonin said in QProcess::readAll and QProcess::readAllStandardOutput both return an empty string after QProcess::write() is run:

              hi

              Thank you very much for the solution!

              Just one small issue:

              error: ‘connect’ was not declared in this scope
                   connect(p,&QProcess::finished,&looper,&QEventLoop::quit);
                                                                          ^
              

              Not so sure about this one...

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #7

                put QObject:: in front, edited the code above

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                CybeXC 1 Reply Last reply
                0
                • VRoninV VRonin

                  put QObject:: in front, edited the code above

                  CybeXC Offline
                  CybeXC Offline
                  CybeX
                  wrote on last edited by
                  #8

                  @VRonin hi, same 'same' error

                  My includes for what it is worth

                  #include <QCoreApplication>
                  #include <QLoggingCategory>
                  #include <QTextStream>
                  #include <QProcess>
                  #include <QString>
                  #include <QVariant>
                  #include <QDebug>
                  #include <QObject>
                  #include <QEventLoop>
                  

                  Edited Code as give above:

                  QString runCommand(const QString& cmd, const QString& input){
                  
                      //I ignore cmd for testing purposes. I use a straightup cd to script and execute
                  
                      QString result;
                      QEventLoop looper;
                      QProcess *p = new QProcess(&looper);
                      p->setProcessChannelMode(QProcess::MergedChannels);
                      QObject::connect(p,&QProcess::finished,&looper,&QEventLoop::quit);
                      QObject::connect(p,&QProcess::errorOccurred,[&result]()->void{qDebug("Error in Process"); result.clear();});
                      QObject::connect(p,&QProcess::errorOccurred,&looper,&QEventLoop::quit);
                      QObject::connect(p,&QProcess::started,[p,&input]()->void{p->write((input +'\n').toLatin1());});
                      QObject::connect(p,&QProcess::readyReadStandardOutput,[p,&result]()->void{result+=p->readAllStandardOutput();});
                      const QString c = QString("sh -c \" cd /home/dev; ./script\" ");
                      p->start(c);
                      looper.exec();
                      return result;
                  }
                  

                  Error:

                  main.cpp:296: error: no matching function for call to ‘QObject::connect(QProcess*&, <unresolved overloaded function type>, QEventLoop*, void (QEventLoop::*)())’
                       QObject::connect(p,&QProcess::finished,&looper,&QEventLoop::quit);
                                                                                       ^
                  
                  1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #9

                    My bad. if it happens again look at the documentation for the signal and/or slot (depending where <unresolved overloaded function type> appears). In this case: http://doc.qt.io/qt-5/qprocess.html#finished

                    so instead of &QProcess::finished use static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished)

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    1
                    • T Offline
                      T Offline
                      tarod.net
                      wrote on last edited by
                      #10

                      I would like to post my Stack Oveflow answer. It's actually an example where we write the name and get also the output given by the script.

                      Code:

                      #include <QCoreApplication>
                      #include <QProcess>
                      #include <QDebug>
                      
                      class MyProcess : public QProcess
                      {
                          Q_OBJECT
                      
                      public:
                          MyProcess(QObject *parent = 0);
                          ~MyProcess() {}
                      
                      public slots:
                          void myReadyRead();
                          void myReadyReadStandardOutput();
                      };
                      
                      MyProcess::MyProcess(QObject *parent)
                      {
                          connect(this,SIGNAL(readyRead()),
                                  this,SLOT(myReadyRead()));
                          connect(this,SIGNAL(readyReadStandardOutput()),
                                  this,SLOT(myReadyReadStandardOutput()));
                      }
                      
                      void MyProcess::myReadyRead() {
                          qDebug() << Q_FUNC_INFO;
                      }
                      
                      void MyProcess::myReadyReadStandardOutput() {
                          qDebug() << Q_FUNC_INFO;
                          // Note we need to add \n (it's like pressing enter key)
                          this->write(QString("myname" + QString("\n")).toLatin1());
                          // Next line no required
                          // qDebug() << this->readAll();
                          qDebug() << this->readAllStandardOutput();
                      
                      }
                      
                      int main(int argc, char *argv[])
                      {
                          QCoreApplication a(argc, argv);
                      
                          MyProcess *myProcess = new MyProcess();
                      
                          QString program = "/home/fran/code/myscript.sh";
                      
                          myProcess->start("/bin/sh", QStringList() << program);
                      
                          a.exec();
                      }
                      
                      #include "main.moc"
                      

                      Script:

                      echo "enter your name:"
                      read n
                      if [ ! -z "$n" ];
                      then
                              echo "success"
                              exit 0;
                      else
                              echo "failed"
                              exit 1;
                      fi
                      

                      "Individually, we are one drop. Together, we are an ocean."

                      CybeXC sitesvS 2 Replies Last reply
                      2
                      • T tarod.net

                        I would like to post my Stack Oveflow answer. It's actually an example where we write the name and get also the output given by the script.

                        Code:

                        #include <QCoreApplication>
                        #include <QProcess>
                        #include <QDebug>
                        
                        class MyProcess : public QProcess
                        {
                            Q_OBJECT
                        
                        public:
                            MyProcess(QObject *parent = 0);
                            ~MyProcess() {}
                        
                        public slots:
                            void myReadyRead();
                            void myReadyReadStandardOutput();
                        };
                        
                        MyProcess::MyProcess(QObject *parent)
                        {
                            connect(this,SIGNAL(readyRead()),
                                    this,SLOT(myReadyRead()));
                            connect(this,SIGNAL(readyReadStandardOutput()),
                                    this,SLOT(myReadyReadStandardOutput()));
                        }
                        
                        void MyProcess::myReadyRead() {
                            qDebug() << Q_FUNC_INFO;
                        }
                        
                        void MyProcess::myReadyReadStandardOutput() {
                            qDebug() << Q_FUNC_INFO;
                            // Note we need to add \n (it's like pressing enter key)
                            this->write(QString("myname" + QString("\n")).toLatin1());
                            // Next line no required
                            // qDebug() << this->readAll();
                            qDebug() << this->readAllStandardOutput();
                        
                        }
                        
                        int main(int argc, char *argv[])
                        {
                            QCoreApplication a(argc, argv);
                        
                            MyProcess *myProcess = new MyProcess();
                        
                            QString program = "/home/fran/code/myscript.sh";
                        
                            myProcess->start("/bin/sh", QStringList() << program);
                        
                            a.exec();
                        }
                        
                        #include "main.moc"
                        

                        Script:

                        echo "enter your name:"
                        read n
                        if [ ! -z "$n" ];
                        then
                                echo "success"
                                exit 0;
                        else
                                echo "failed"
                                exit 1;
                        fi
                        
                        CybeXC Offline
                        CybeXC Offline
                        CybeX
                        wrote on last edited by CybeX
                        #11

                        Original SO thread

                        1 Reply Last reply
                        0
                        • T tarod.net

                          I would like to post my Stack Oveflow answer. It's actually an example where we write the name and get also the output given by the script.

                          Code:

                          #include <QCoreApplication>
                          #include <QProcess>
                          #include <QDebug>
                          
                          class MyProcess : public QProcess
                          {
                              Q_OBJECT
                          
                          public:
                              MyProcess(QObject *parent = 0);
                              ~MyProcess() {}
                          
                          public slots:
                              void myReadyRead();
                              void myReadyReadStandardOutput();
                          };
                          
                          MyProcess::MyProcess(QObject *parent)
                          {
                              connect(this,SIGNAL(readyRead()),
                                      this,SLOT(myReadyRead()));
                              connect(this,SIGNAL(readyReadStandardOutput()),
                                      this,SLOT(myReadyReadStandardOutput()));
                          }
                          
                          void MyProcess::myReadyRead() {
                              qDebug() << Q_FUNC_INFO;
                          }
                          
                          void MyProcess::myReadyReadStandardOutput() {
                              qDebug() << Q_FUNC_INFO;
                              // Note we need to add \n (it's like pressing enter key)
                              this->write(QString("myname" + QString("\n")).toLatin1());
                              // Next line no required
                              // qDebug() << this->readAll();
                              qDebug() << this->readAllStandardOutput();
                          
                          }
                          
                          int main(int argc, char *argv[])
                          {
                              QCoreApplication a(argc, argv);
                          
                              MyProcess *myProcess = new MyProcess();
                          
                              QString program = "/home/fran/code/myscript.sh";
                          
                              myProcess->start("/bin/sh", QStringList() << program);
                          
                              a.exec();
                          }
                          
                          #include "main.moc"
                          

                          Script:

                          echo "enter your name:"
                          read n
                          if [ ! -z "$n" ];
                          then
                                  echo "success"
                                  exit 0;
                          else
                                  echo "failed"
                                  exit 1;
                          fi
                          
                          sitesvS Offline
                          sitesvS Offline
                          sitesv
                          wrote on last edited by
                          #12

                          @tarod-net
                          Hi!
                          I have this output without input stream from keyboard:

                          void MyProcess::myReadyRead()
                          void MyProcess::myReadyReadStandardOutput()
                          "enter your name\n"
                          void MyProcess::myReadyRead()
                          void MyProcess::myReadyReadStandardOutput()
                          "success\n"
                          

                          Is this correct?

                          JonBJ 1 Reply Last reply
                          0
                          • sitesvS sitesv

                            @tarod-net
                            Hi!
                            I have this output without input stream from keyboard:

                            void MyProcess::myReadyRead()
                            void MyProcess::myReadyReadStandardOutput()
                            "enter your name\n"
                            void MyProcess::myReadyRead()
                            void MyProcess::myReadyReadStandardOutput()
                            "success\n"
                            

                            Is this correct?

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by
                            #13

                            @sitesv said in QProcess::readAll and QProcess::readAllStandardOutput both return an empty string after QProcess::write() is run:

                            Is this correct?

                            As code? No.

                            sitesvS 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @sitesv said in QProcess::readAll and QProcess::readAllStandardOutput both return an empty string after QProcess::write() is run:

                              Is this correct?

                              As code? No.

                              sitesvS Offline
                              sitesvS Offline
                              sitesv
                              wrote on last edited by
                              #14

                              @JonB I don't know why this example does the output like this....

                              1 Reply Last reply
                              0
                              • B Offline
                                B Offline
                                Bitbrat
                                wrote on last edited by
                                #15

                                QProcess has quite extensive support for synchronous use.

                                #include <QCoreApplication>
                                #include <QDebug>
                                #include <QProcess>
                                
                                int main(int argc, char **argv)
                                {
                                    QCoreApplication app(argc, argv);
                                
                                    QProcess process;
                                    process.start("ls", {"-l"});
                                    if (process.waitForFinished()) {
                                        qDebug() << "returned:" << process.readAllStandardOutput();
                                    } else {
                                        qDebug() << process.errorString();
                                    }
                                
                                    process.start("ls", {"-l"});
                                    while (process.waitForReadyRead()) {
                                        while (process.canReadLine())
                                            qDebug() << process.readLine().trimmed();
                                    }
                                }
                                
                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved