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