Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. How to make QProcess "interactive" ?
Forum Update on Monday, May 27th 2025

How to make QProcess "interactive" ?

Scheduled Pinned Locked Moved Unsolved C++ Gurus
15 Posts 5 Posters 2.2k 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.
  • A Anonymous_Banned275

    @AnneRanch I would like to "rephrase" my question

    why it this code
    starts Linux "terminal" .and prints correct response

    and FAILS to detect it ?

                        void MainWindow_Bluewtoothctl_Dialog::on_pushButton_21_clicked()
                            {
    
                                text = " DEBUG terminal.... ";
                                text = Q_FUNC_INFO;
                                text += "  @ line  ";
                                text += QString::number(__LINE__);
                                ui->textEdit_2->append(text); // debug
                                qDebug()<<text;
                                //text = " DEBUG  TEST  hcitool info 98:D3:31:F8:39:33";
                                //''ui->textEdit_2->append(text);
                                // text  = "sudo ls " ;
    
                                QProcess *process;
                                process = new QProcess();
                                //process->start("hcitool", QStringList() << "dev");
                                process->start("/usr/bin/gnome-terminal", QStringList() << "lsusb");
                                if(process->Running)
                                {
                                    text = "process->Running  OK ";
                                    ui->textEdit_2->append(text);
                                    qDebug() << text;
    
    **THIS CODE FAILS** 
                                    if(process->waitForReadyRead())
                                    {
                                        text = "process->waitForReadyRead()  OK ";
                                        ui->textEdit_2->append(text);
                                        qDebug() << text;
                                    }
                                    else
                                    {
                                        text = "process->waitForReadyRead()  FAILED  ";
                                        ui->textEdit_2->append(text);
                                        qDebug() << text;
                                    }
                                    // what is fail value ??
                                    if(process->waitForReadyRead() && process->waitForFinished())
                                    {
                                        // qDebug() << process->StandardOutput;
                                        result = process->readAllStandardOutput();
                                        qDebug() << result;
                                        ui->textEdit_2->append(result);
                                    }
                                    else
                                    {
                                        qDebug()<< "FAILED process->waitForReadyRead() && process->waitForFinished()";
                                        process->write("q\n");
                                        if(process->waitForReadyRead() && process->waitForFinished())
                                        {
                                            // qDebug() << process->StandardOutput;
                                            result = process->readAllStandardOutput();
                                            qDebug() << result;
                                            ui->textEdit_2->append(result);
                                        }
                                        else
                                        {
                                            qDebug()<< "FAILED AFTER WRITE process->waitForReadyRead() && process->waitForFinished()";
                                        }
    
                                    }
    
                                }
                                else
                                {
                                    qDebug()<< "FAILED process did not start!!!!!!!!!!!!!!!!!!!!!!!!!!!";
                                }
                                return;
                            }
    
    
    TomZT Offline
    TomZT Offline
    TomZ
    wrote on last edited by TomZ
    #6

    @AnneRanch said in How to make QProcess "interactive" ?:

    why it this code

    frankly, there is more wrong with this code than correct. (I'm Dutch, sorry we're blunt).

    You've missed the async nature of Qt, for starters. You should NEVER call methods like "wait for" in a callback from the UI.

    As others indicated, sudo is specifically designed to not allow this. The structural solution is policyKit, as generally it's a bad approach to make a button press start an admin process.

    Which then leads to the point that QProcess is not meant for this kind of thing either. Good examples of QProcess are a front-end for Git that calls git commands behind the scenes. Bad examples are anything that requires any type of interaction. It's not impossible, just not a good idea.

    Bottom line; use policyKit, or its newer version polkit.

    A 1 Reply Last reply
    2
    • TomZT TomZ

      @AnneRanch said in How to make QProcess "interactive" ?:

      why it this code

      frankly, there is more wrong with this code than correct. (I'm Dutch, sorry we're blunt).

      You've missed the async nature of Qt, for starters. You should NEVER call methods like "wait for" in a callback from the UI.

      As others indicated, sudo is specifically designed to not allow this. The structural solution is policyKit, as generally it's a bad approach to make a button press start an admin process.

      Which then leads to the point that QProcess is not meant for this kind of thing either. Good examples of QProcess are a front-end for Git that calls git commands behind the scenes. Bad examples are anything that requires any type of interaction. It's not impossible, just not a good idea.

      Bottom line; use policyKit, or its newer version polkit.

      A Offline
      A Offline
      Anonymous_Banned275
      wrote on last edited by Anonymous_Banned275
      #7

      @TomZ OK, you can be blunt, but I cannot...
      Here it the minimal explanation for my need for interactive QProcess...I am writing Bluetooth application for my own use - hence I am not concerned about the use or misuse of "sudo'-- end of story.
      I started by using Qt Bluetooth code to find out it has "few holes" .. the main one - it does not always physically scan for devices - it uses RANDOM unknown data from past...

      So I switched to using fundamental Linux commands , hence I really need interactive code.

      I understand "interactive " can be done using output redirection or "native window"... and I am heading that direction.

      TomZT 1 Reply Last reply
      0
      • A Anonymous_Banned275

        @TomZ OK, you can be blunt, but I cannot...
        Here it the minimal explanation for my need for interactive QProcess...I am writing Bluetooth application for my own use - hence I am not concerned about the use or misuse of "sudo'-- end of story.
        I started by using Qt Bluetooth code to find out it has "few holes" .. the main one - it does not always physically scan for devices - it uses RANDOM unknown data from past...

        So I switched to using fundamental Linux commands , hence I really need interactive code.

        I understand "interactive " can be done using output redirection or "native window"... and I am heading that direction.

        TomZT Offline
        TomZT Offline
        TomZ
        wrote on last edited by
        #8

        @AnneRanch thank you for taking my message in stride :-)

        I just want to first up state that the reason I suggested to not use sudo interactively is not because I'm playing the responsible parent or anything.
        The reason I'm saying this is because the sudo authors went out of their way to make it very hard to do this. Again, sudo and interactively..

        If you need to use sudo, make sure you can do this non-interactively. Which means to do so passwordless for those commands you need executed as root.
        You can get started with that here:
        https://help.ubuntu.com/community/Sudoers


        Now, you write your bluetooth app requires you to do things interactively, presumably with commandline tools. Not sure if I got that part. Things like lsusb don't require sudo, so your example didn't enlighten me.

        As I wrote, you can make qprocess be interactive.

        You want to write a class that owns it and work in async manner (using signals and slots) without any wait type of methods. Ideally your apps that run as root never touch stderr, which makes it much easier and you'll be able to find and use any type of QIODevice based tutorial on how to interactively send and receive data.

        A 1 Reply Last reply
        0
        • TomZT TomZ

          @AnneRanch thank you for taking my message in stride :-)

          I just want to first up state that the reason I suggested to not use sudo interactively is not because I'm playing the responsible parent or anything.
          The reason I'm saying this is because the sudo authors went out of their way to make it very hard to do this. Again, sudo and interactively..

          If you need to use sudo, make sure you can do this non-interactively. Which means to do so passwordless for those commands you need executed as root.
          You can get started with that here:
          https://help.ubuntu.com/community/Sudoers


          Now, you write your bluetooth app requires you to do things interactively, presumably with commandline tools. Not sure if I got that part. Things like lsusb don't require sudo, so your example didn't enlighten me.

          As I wrote, you can make qprocess be interactive.

          You want to write a class that owns it and work in async manner (using signals and slots) without any wait type of methods. Ideally your apps that run as root never touch stderr, which makes it much easier and you'll be able to find and use any type of QIODevice based tutorial on how to interactively send and receive data.

          A Offline
          A Offline
          Anonymous_Banned275
          wrote on last edited by
          #9

          @TomZ Thanks for reply.

          Allow me to modify this discussion.

          Here is my FULL TEST code.

          MainWindow::MainWindow(QWidget *parent)
              : QMainWindow(parent)
              , ui(new Ui::MainWindow)
          {
              ui->setupUi(this);
              QProcess *QP = new QProcess();
              QP->start( "/usr/bin/gnome-terminal", QStringList() <<  "  lsusb ");
              //QP->write("lsusb");
          }
          
          MainWindow::~MainWindow()
          {
              delete ui;
          }
          
          

          here is FULL run output

          bf631560-7f31-4dc8-92ad-f4d208f534dd-image.png

          the "start" HAS option "lsusb" there is NO " sudo" required

          AND there is no " lsusb" output

          BUT I can input "lsusb" manually and get expected data .
          however I desire to have interactive ( read/ write ) code.

          PS the doc clearly states this is
          how QPocess should work.

          "The QProcess class is used to start external programs and to communicate with them."

          The question remains - what is missing in code ?

          JonBJ Axel SpoerlA 2 Replies Last reply
          0
          • A Anonymous_Banned275

            @TomZ Thanks for reply.

            Allow me to modify this discussion.

            Here is my FULL TEST code.

            MainWindow::MainWindow(QWidget *parent)
                : QMainWindow(parent)
                , ui(new Ui::MainWindow)
            {
                ui->setupUi(this);
                QProcess *QP = new QProcess();
                QP->start( "/usr/bin/gnome-terminal", QStringList() <<  "  lsusb ");
                //QP->write("lsusb");
            }
            
            MainWindow::~MainWindow()
            {
                delete ui;
            }
            
            

            here is FULL run output

            bf631560-7f31-4dc8-92ad-f4d208f534dd-image.png

            the "start" HAS option "lsusb" there is NO " sudo" required

            AND there is no " lsusb" output

            BUT I can input "lsusb" manually and get expected data .
            however I desire to have interactive ( read/ write ) code.

            PS the doc clearly states this is
            how QPocess should work.

            "The QProcess class is used to start external programs and to communicate with them."

            The question remains - what is missing in code ?

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

            @AnneRanch
            Because it is not running lsusb? Your command is /usr/bin/gnome-terminal lsusb. I don't think that is right, did you try copying and pasting that onto a command line to test? If it's not right there it won;t be right from QProcess. From what I can see you might need any of these:

            /usr/bin/gnome-terminal --command lsusb
            /usr/bin/gnome-terminal --exec lsusb
            /usr/bin/gnome-terminal -e lsusb
            /usr/bin/gnome-terminal -x lsusb
            /usr/bin/gnome-terminal -- lsusb
            

            Look at https://manpages.ubuntu.com/manpages/xenial/en/man1/gnome-terminal.1.html or try man gnome-terminal or gnome-terminal --help on your system.

            1 Reply Last reply
            0
            • kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #11

              @AnneRanch said in How to make QProcess "interactive" ?:

              Here is my FULL TEST code.

              ... your full test code doesn't read the standard output of the started process.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              2
              • A Anonymous_Banned275

                @TomZ Thanks for reply.

                Allow me to modify this discussion.

                Here is my FULL TEST code.

                MainWindow::MainWindow(QWidget *parent)
                    : QMainWindow(parent)
                    , ui(new Ui::MainWindow)
                {
                    ui->setupUi(this);
                    QProcess *QP = new QProcess();
                    QP->start( "/usr/bin/gnome-terminal", QStringList() <<  "  lsusb ");
                    //QP->write("lsusb");
                }
                
                MainWindow::~MainWindow()
                {
                    delete ui;
                }
                
                

                here is FULL run output

                bf631560-7f31-4dc8-92ad-f4d208f534dd-image.png

                the "start" HAS option "lsusb" there is NO " sudo" required

                AND there is no " lsusb" output

                BUT I can input "lsusb" manually and get expected data .
                however I desire to have interactive ( read/ write ) code.

                PS the doc clearly states this is
                how QPocess should work.

                "The QProcess class is used to start external programs and to communicate with them."

                The question remains - what is missing in code ?

                Axel SpoerlA Offline
                Axel SpoerlA Offline
                Axel Spoerl
                Moderators
                wrote on last edited by
                #12

                @AnneRanch said in How to make QProcess "interactive" ?:

                "The QProcess class is used to start external programs and to communicate with them."

                You misinterpret the documentation. QProcessstarts external programs and communicates with them. What you want to do, is to start an external program, let the user communicate with it in a defined manner and read back the result. As said before: Not possible in Qt and I wouldn't know of any well known tool, that is suitable for such a contained user interaction.

                And just on a side note: Your full test code leaks a QProcess - an eye catching antipattern.

                Software Engineer
                The Qt Company, Oslo

                1 Reply Last reply
                1
                • JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #13

                  @kshegunov , @Axel-Spoerl
                  Your comments are, of course, quite correct, However, I would remind you and OP that, as per my first reply, the command being issued is /usr/bin/gnome-terminal lsusb. This is an incorrect command line for /usr/bin/gnome-terminal. The trailing lsusb is simply ignored in this case, it is not run, and instead an interactive terminal is simply opened, just as the screenshot shows.

                  Furthermore, as also discussed in the past, a terminal such as /usr/bin/gnome-terminal (with or without the correct arguments to cause it to run a command) simply does not produce any output on the stdout, so nothing can be read from QProcess from it. Consider the following:

                  gnome-terminal -- find / -print
                  

                  [We have to call something which produces voluminous output, else the terminal window opens, runs the command and closes so quickly that you do not see anything.] You see the output running by in the opened terminal, till it concludes. Now try

                  jon@ubuntu-22:~$ gnome-terminal -- find / -print > output
                  jon@ubuntu-22:~$ ls -l output
                  -rw-rw-r-- 1 jon jon 0 Feb 16 09:47 output
                  

                  Same behaviour as without the attempted redirection: the output appears in the opened terminal window, and at the end nothing has been written into output file, i.e. redirection from calling program captures nothing.

                  Terminals such as gnome-terminal (and the others, e..g xterm) start by creating a window and attaching their stdout to that (pseudo-tty). You cannot get at their output via the normal redirection which would work on a command without running it in a terminal. I have said this to OP in the past for just this question.

                  A 1 Reply Last reply
                  2
                  • JonBJ JonB

                    @kshegunov , @Axel-Spoerl
                    Your comments are, of course, quite correct, However, I would remind you and OP that, as per my first reply, the command being issued is /usr/bin/gnome-terminal lsusb. This is an incorrect command line for /usr/bin/gnome-terminal. The trailing lsusb is simply ignored in this case, it is not run, and instead an interactive terminal is simply opened, just as the screenshot shows.

                    Furthermore, as also discussed in the past, a terminal such as /usr/bin/gnome-terminal (with or without the correct arguments to cause it to run a command) simply does not produce any output on the stdout, so nothing can be read from QProcess from it. Consider the following:

                    gnome-terminal -- find / -print
                    

                    [We have to call something which produces voluminous output, else the terminal window opens, runs the command and closes so quickly that you do not see anything.] You see the output running by in the opened terminal, till it concludes. Now try

                    jon@ubuntu-22:~$ gnome-terminal -- find / -print > output
                    jon@ubuntu-22:~$ ls -l output
                    -rw-rw-r-- 1 jon jon 0 Feb 16 09:47 output
                    

                    Same behaviour as without the attempted redirection: the output appears in the opened terminal window, and at the end nothing has been written into output file, i.e. redirection from calling program captures nothing.

                    Terminals such as gnome-terminal (and the others, e..g xterm) start by creating a window and attaching their stdout to that (pseudo-tty). You cannot get at their output via the normal redirection which would work on a command without running it in a terminal. I have said this to OP in the past for just this question.

                    A Offline
                    A Offline
                    Anonymous_Banned275
                    wrote on last edited by
                    #14

                    @JonB said in How to make QProcess "interactive" ?:

                    the output appears in the opened terminal window,

                    Please explain the above - if it is is NOT "'stdxx" what is it ?

                    ... and why QProcess does not pass the "lsusb" at all?
                    is it not passed as an "option"?

                    JonBJ 1 Reply Last reply
                    0
                    • A Anonymous_Banned275

                      @JonB said in How to make QProcess "interactive" ?:

                      the output appears in the opened terminal window,

                      Please explain the above - if it is is NOT "'stdxx" what is it ?

                      ... and why QProcess does not pass the "lsusb" at all?
                      is it not passed as an "option"?

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

                      @AnneRanch
                      Anne, I explained both of these above. You ask for clarification but what can I say further to what In have written? Summary:

                      • The command you are issuing, gnome-terminal lsusb, is not and never has been the correct syntax to ask gnome-terminal to run a command. It ignores the lsusb completely and simply runs gnome-terminal. So you see an interactive terminal window sitting there instead. For Ubuntu the command should be gnome-terminal -- lsusb. That will open the window, run lsusb and close the window when that finishes. Which happens so quickly in milliseconds that you simply won't see anything, the window will open and close faster than you can see. Which is why I said if you were to run gnome-terminal -- find / -print you will get to see what actually is happening. You can try these outside of your Qt program from a terminal.

                      • If you invoke gnome-terminal, or any other "terminal" such as xterm, to run a command (such as lsusb) the terminal will attach its stdout to the window it opens. That means no matter what your calling program --- a Linux shell or a Qt application --- it will not receive or be able to access any output the command (lsusb or whatever) produces e.g. on its stdout. That will go to the terminal window and cannot be seen by the calling application.

                      As per when we discussed this a year or two ago and I said then, if you want to be able to read back the output from, say, lsusb you must run it directly (as the command you tell QProcess to start) and not invoke any gnome-terminal or xterm or other terminal to run it.

                      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