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::execute capture output
QtWS25 Last Chance

QProcess::execute capture output

Scheduled Pinned Locked Moved Solved General and Desktop
qprocessexecute
13 Posts 3 Posters 28.7k 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.
  • J Offline
    J Offline
    Jan-Willem
    wrote on last edited by
    #1

    Hi,

    When I start bash through a QProcess, I use QProcess::execute to execute the commands. The QProcess is through the readyRead-signal connected to a method that appends the output in a QPlainRexrEdtit. The documentation says of QProcess::execute:

    Starts the program program with the arguments arguments in a new process, waits for it to finish, and then returns the exit code of the process. Any data the new process writes to the console is forwarded to the calling process.

    However, the output of the new process is written tot the Application output of QtCreator or to the terminal if the application is started from there. How can I capture the output of the child process?

    setProcessChannelMode and setInputChannelMode did not work for this.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Isn't rather readyReadStandardOutput what you are looking for ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • J Offline
        J Offline
        Jan-Willem
        wrote on last edited by
        #3

        @SGaist

        I made a simple example.

        // in constructor
        connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
        
        // slot connected to a QAction
        void Widget::runProcess()
        {
            QString sh = qgetenv("SHELL");
            process.setProgram(sh);
            process.setArguments(QStringList() << "-i");
            process.start();
        
            process.write("ls"); // first test
            // process.execute("ls"); // second test
        
            process.closeWriteChannel();
        }
        
        // slot connected to QProcess::finished
        void Widget::readOutput()
        {
            plainTextEdit->appendPlainText("readOutput");
            plainTextEdit->appendPlainText(process.readAllStandardError());
            plainTextEdit->appendPlainText(process.readAllStandardOutput());
        }
        

        In the first test QProcess::readAllStandardOutput() gives me the string "readOutput" and the listing of the current working directory in the plainTextEdit.

        For the second test I changed the following in Widget::runProcess():

            // process.write("ls"); // first test
            process.execute("ls"); // second test
        

        In the second test readyReadStandardOutput() is not emitted and the listing of the current working directory is show in the Application Output pane in QtCreator.

        I expected the output forwarded to the defined QProcess process, but it seems to be forwarded to the main application. Any ideas how I can get it in the calling QProcess process?

        jsulmJ 1 Reply Last reply
        0
        • J Jan-Willem

          @SGaist

          I made a simple example.

          // in constructor
          connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
          
          // slot connected to a QAction
          void Widget::runProcess()
          {
              QString sh = qgetenv("SHELL");
              process.setProgram(sh);
              process.setArguments(QStringList() << "-i");
              process.start();
          
              process.write("ls"); // first test
              // process.execute("ls"); // second test
          
              process.closeWriteChannel();
          }
          
          // slot connected to QProcess::finished
          void Widget::readOutput()
          {
              plainTextEdit->appendPlainText("readOutput");
              plainTextEdit->appendPlainText(process.readAllStandardError());
              plainTextEdit->appendPlainText(process.readAllStandardOutput());
          }
          

          In the first test QProcess::readAllStandardOutput() gives me the string "readOutput" and the listing of the current working directory in the plainTextEdit.

          For the second test I changed the following in Widget::runProcess():

              // process.write("ls"); // first test
              process.execute("ls"); // second test
          

          In the second test readyReadStandardOutput() is not emitted and the listing of the current working directory is show in the Application Output pane in QtCreator.

          I expected the output forwarded to the defined QProcess process, but it seems to be forwarded to the main application. Any ideas how I can get it in the calling QProcess process?

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

          @Jan-Willem execute() is a static method! It is not related to your QProcess instance which you connected to your slot.
          You should replace

          process.setProgram(sh);
          

          with

          process.setProgram("ls");
          

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

          1 Reply Last reply
          1
          • J Offline
            J Offline
            Jan-Willem
            wrote on last edited by
            #5

            @jsulm thanks for the clarification. The I have interpreted the use of execute() wrong.
            I know

            process.setProgram("ls");
            

            works. But I was trying to create a bash-session because of the variables defined in .bashrc.
            The output of the QProcess seems to be only available after the QProcess is finished. Consider this:

            process.setProgram("/bin/bash");
            process.start();
            process.write("pwd\n");
            process.write("cd ..\n");
            process.write("pwd");
            

            This gives the desired result, but the output is received only when the QProcess is finished. And then the bash-session is closed, so the result of cd is not there anymore.
            You see my problem? I can't seem to find a way around it.

            jsulmJ 1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              What exactly do you want to do with your serie of commands ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • J Jan-Willem

                @jsulm thanks for the clarification. The I have interpreted the use of execute() wrong.
                I know

                process.setProgram("ls");
                

                works. But I was trying to create a bash-session because of the variables defined in .bashrc.
                The output of the QProcess seems to be only available after the QProcess is finished. Consider this:

                process.setProgram("/bin/bash");
                process.start();
                process.write("pwd\n");
                process.write("cd ..\n");
                process.write("pwd");
                

                This gives the desired result, but the output is received only when the QProcess is finished. And then the bash-session is closed, so the result of cd is not there anymore.
                You see my problem? I can't seem to find a way around it.

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

                @Jan-Willem Maybe you should do

                process.write("cd ..\n");
                process.write("pwd");
                

                after you got the output of the first pwd? Because currently you're flooding the shell with commands without waiting for them to finish.

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

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  Jan-Willem
                  wrote on last edited by
                  #8

                  @SGaist I'm experimenting with building a simple terminal window. The series of commands are only for testing. It could be any command for that matter.
                  @jsulm Thanks, I suspected that. But the output never comes, unless I close the writingchannel or what for the process to finish.

                  If I write:

                  process.write("pwd\n");
                  process.write("ls\n");
                  process.write("pwd\n");
                  

                  it works as expected. The output after each step is shown. cmd does not generate output, but the result is also not shown on the last call of pwd.

                  When I create a custom object through which the process is started and then connect it to a Q(Plain)TextEdit, then everything seems to work. I'm trying to understand the reason why.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    Do you have something like Konsole in mind ?

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      Jan-Willem
                      wrote on last edited by
                      #10

                      Yes, but much more simple.
                      I have looked into that code and from a derived project QTermWidget.

                      It seems I now have a working solution, but I try to understand why this works.

                      1 Reply Last reply
                      0
                      • J Offline
                        J Offline
                        Jan-Willem
                        wrote on last edited by
                        #11

                        I have started from scratch to see what my problem actually was, but I wasn't able to reproduce it.
                        I probably got lost somewhere in my code.

                        Well, below is the working code for the curious.

                        @SGaist @jsulm Thanks for your help!

                        Widget::Widget(QWidget *parent)
                            : QWidget(parent)
                        {
                            QPlainTextEdit *plainTextEdit = new QPlainTextEdit(this);
                            plainTextEdit->setReadOnly(true);
                        
                            QLineEdit *lineEdit = new QLineEdit(this);
                            lineEdit->setClearButtonEnabled(true);
                        
                            QVBoxLayout *layout = new QVBoxLayout;
                            layout->addWidget(plainTextEdit);
                            layout->addWidget(lineEdit);
                            setLayout(layout);
                        
                            connect(&process, &QProcess::readyReadStandardOutput, [=](){ plainTextEdit->appendPlainText(process.readAllStandardOutput()); });
                            connect(&process, &QProcess::readyReadStandardError, [=](){ plainTextEdit->appendPlainText(process.readAllStandardError()); });
                            connect(&process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &Widget::close);
                            connect(lineEdit, &QLineEdit::returnPressed, [=](){ process.write(lineEdit->text().toLatin1() + "\n"); lineEdit->clear(); });
                        
                            process.start("sh");
                        }
                        
                        Widget::~Widget()
                        {
                            process.close();
                        }
                        
                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          If you have a recent enough version of Qt, you can use qOverload in place of static_cast. It will do the same but will be more readable.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          1
                          • J Offline
                            J Offline
                            Jan-Willem
                            wrote on last edited by
                            #13

                            @SGaist Good one! Though I had to use the C++11 version since C++14 is still in Debian Sid.

                            // C++11
                            connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &MainWindow::close);
                            

                            For those who want to know, this is the C++14-version:

                            // C++14
                            connect(process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, &MainWindow::close);
                            

                            Since the actual problem of this thread is solved, I will mark this thread as solved tomorrow. In the mean time comments on the above code can be made.

                            1 Reply Last reply
                            2

                            • Login

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