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
    #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