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 and stdout
Forum Updated to NodeBB v4.3 + New Features

QProcess and stdout

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 4 Posters 1.6k Views 1 Watching
  • 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.
  • D Offline
    D Offline
    Devolution
    wrote on last edited by Devolution
    #1

    Hello, I'm trying to call a binary (namely youtube-dl) using QProcess.

    Relevant code is the following:

        QProcess * ytdl = new QProcess();
    
    
        QObject::connect(ytdl,&QProcess::started, [=]{
            qDebug() << "STARTED";
        });
    
        QObject::connect(ytdl, &QProcess::readyReadStandardOutput, [=]{
             qDebug() << ytdl->readAllStandardOutput();
        });
        QObject::connect(ytdl, &QProcess::readyReadStandardError, [=]{
              qDebug() << ytdl->readAllStandardError();
        });
        QObject::connect(ytdl,QOverload<int>::of(&QProcess::finished), [=]{
            qDebug() << "Youtubedl ended nam";
            ytdl->deleteLater();
        });
    
                ytdl->setWorkingDirectory(QApplication::applicationDirPath());
                ytdl->setProcessChannelMode( QProcess::MergedChannels ); // merge stderr and stdout
    
                ytdl->setReadChannel(QProcess::StandardOutput);
                ytdl->start("cmd" , QStringList() <<"/C" << "D:\\youtube-dl.exe") ; 
    

    If i run the code as is, i only get the STARTED output in the qDebug terminal.
    However, if i add waitForFinished() i get all the output text at once.
    The start command i used is very small and should return the usage of youtube-dl, it's basically instant, and even after waiting a few minutes nothing is printed in the qDebug window without waitForFinished().

    The thing is i want this to be asynchronous, and not blocking.

    Could you provide help on this issue? Thanks in advance for any hints :)

    1 Reply Last reply
    0
    • eyllanescE Offline
      eyllanescE Offline
      eyllanesc
      wrote on last edited by
      #2

      @Devolution try changing to ytdl->start("D:\\youtube-dl.exe") ;

      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

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

        Hi and welcome to devnet,

        You forgot to connect the errorOccured signal in case something went wrong.

        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
        • eyllanescE eyllanesc

          @Devolution try changing to ytdl->start("D:\\youtube-dl.exe") ;

          D Offline
          D Offline
          Devolution
          wrote on last edited by Devolution
          #4

          @eyllanesc said in QProcess and stdout:

          @Devolution try changing to ytdl->start("D:\\youtube-dl.exe") ;

          Hi,
          I tried with that, the result is the same.

          @SGaist said in QProcess and stdout:

          Hi and welcome to devnet,

          You forgot to connect the errorOccured signal in case something went wrong.

          Hello, i've now connected the signal, with the following:

          QObject::connect(ytdl,&QProcess::errorOccurred, [=](QProcess::ProcessError error){
               qDebug() << "Error:" << error;
           });
          

          No error is shown and still no output from stderr or stdout.

          JonBJ 1 Reply Last reply
          0
          • D Devolution

            @eyllanesc said in QProcess and stdout:

            @Devolution try changing to ytdl->start("D:\\youtube-dl.exe") ;

            Hi,
            I tried with that, the result is the same.

            @SGaist said in QProcess and stdout:

            Hi and welcome to devnet,

            You forgot to connect the errorOccured signal in case something went wrong.

            Hello, i've now connected the signal, with the following:

            QObject::connect(ytdl,&QProcess::errorOccurred, [=](QProcess::ProcessError error){
                 qDebug() << "Error:" << error;
             });
            

            No error is shown and still no output from stderr or stdout.

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

            @Devolution
            Well there out be some difference, because your original cmd D:\\youtube-dl.exe would not have run it, and should have just produced a Command Prompt message or hung. At least D:\\youtube-dl.exe should run it.

            When you run it (D:\youtube-dl.exe) yourself (outside Qt), does it produce output and exit, or does it stay around?

            1 Reply Last reply
            0
            • D Offline
              D Offline
              Devolution
              wrote on last edited by
              #6

              My bad,
              i forgot the /C in my original post, i edited it. Regardless of cmd /C D:\youtube.dl.exe or D:\youtube-dl.exe there is no output.

              D:\youtube-dl.exe ecuted outside qt (in the execcute window) produces usage output and then shuts off.

              JonBJ 1 Reply Last reply
              0
              • D Devolution

                My bad,
                i forgot the /C in my original post, i edited it. Regardless of cmd /C D:\youtube.dl.exe or D:\youtube-dl.exe there is no output.

                D:\youtube-dl.exe ecuted outside qt (in the execcute window) produces usage output and then shuts off.

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

                @Devolution
                Just to make sure and kinda simulate what is going on with the redirection, please go into a Command Prompt and just verify how D:\youtube-dl.exe | more behaves? Also, just in case, D:\youtube-dl.exe <nul

                Then, comment out all your redirection code. First things first, we are wanting to just get the finished signal, which you are saying you aren't getting.

                Also check when it "hangs" that you can see the youtube-dl.exe process running in Task Manager.

                These are the things I can think of that I would verify.

                D 1 Reply Last reply
                0
                • JonBJ JonB

                  @Devolution
                  Just to make sure and kinda simulate what is going on with the redirection, please go into a Command Prompt and just verify how D:\youtube-dl.exe | more behaves? Also, just in case, D:\youtube-dl.exe <nul

                  Then, comment out all your redirection code. First things first, we are wanting to just get the finished signal, which you are saying you aren't getting.

                  Also check when it "hangs" that you can see the youtube-dl.exe process running in Task Manager.

                  These are the things I can think of that I would verify.

                  D Offline
                  D Offline
                  Devolution
                  wrote on last edited by
                  #8

                  @JonB said in QProcess and stdout:

                  @Devolution
                  Just to make sure and kinda simulate what is going on with the redirection, please go into a Command Prompt and just verify how D:\youtube-dl.exe | more behaves? Also, just in case, D:\youtube-dl.exe <nul

                  Then, comment out all your redirection code. First things first, we are wanting to just get the finished signal, which you are saying you aren't getting.

                  Also check when it "hangs" that you can see the youtube-dl.exe process running in Task Manager.

                  These are the things I can think of that I would verify

                  D:`youtube-dl.exe | more executed in a cmd behaves the same as without | more, that is printing the usage message.

                  I commented the stdout and stderr redirections and the lines relative to the channels, still i got no signal emitted for process done. I can't see any process hanging in the task manager, probably youtube-dl going to fast to shutdown..

                  JonBJ 1 Reply Last reply
                  0
                  • D Devolution

                    @JonB said in QProcess and stdout:

                    @Devolution
                    Just to make sure and kinda simulate what is going on with the redirection, please go into a Command Prompt and just verify how D:\youtube-dl.exe | more behaves? Also, just in case, D:\youtube-dl.exe <nul

                    Then, comment out all your redirection code. First things first, we are wanting to just get the finished signal, which you are saying you aren't getting.

                    Also check when it "hangs" that you can see the youtube-dl.exe process running in Task Manager.

                    These are the things I can think of that I would verify

                    D:`youtube-dl.exe | more executed in a cmd behaves the same as without | more, that is printing the usage message.

                    I commented the stdout and stderr redirections and the lines relative to the channels, still i got no signal emitted for process done. I can't see any process hanging in the task manager, probably youtube-dl going to fast to shutdown..

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

                    @Devolution

                    probably youtube-dl going to fast to shutdown

                    It's not supposed to work that way. So long as you have your slots set up before you start(), which you seem to have done.

                    Hmm. I don't get that you are not seeing finished, yet, say, waitForFinished() is concluding.

                    I haven't used it myself but there is also signal QProcess::stateChanged, https://doc.qt.io/qt-5/qprocess.html#stateChanged. See what states that reports it going through?

                    There is no chance that you are deleting that QProcess elsewhere than in finished, is there?

                    I'm not a C++ expert, certainly not on lambdas. Example at https://doc.qt.io/qt-5/qprocess.html#finished shows:

                    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                        [=](int exitCode, QProcess::ExitStatus exitStatus){ /* ... */ });
                    

                    The QOverload<int, QProcess::ExitStatus> does not seem to match your QOverload<int>? Try with theirs?

                    Finally, check with some quite different .exe elsewhere (preferably producing some output), is the behaviour different from with youtube-dl.exe?

                    D 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @Devolution

                      probably youtube-dl going to fast to shutdown

                      It's not supposed to work that way. So long as you have your slots set up before you start(), which you seem to have done.

                      Hmm. I don't get that you are not seeing finished, yet, say, waitForFinished() is concluding.

                      I haven't used it myself but there is also signal QProcess::stateChanged, https://doc.qt.io/qt-5/qprocess.html#stateChanged. See what states that reports it going through?

                      There is no chance that you are deleting that QProcess elsewhere than in finished, is there?

                      I'm not a C++ expert, certainly not on lambdas. Example at https://doc.qt.io/qt-5/qprocess.html#finished shows:

                      connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                          [=](int exitCode, QProcess::ExitStatus exitStatus){ /* ... */ });
                      

                      The QOverload<int, QProcess::ExitStatus> does not seem to match your QOverload<int>? Try with theirs?

                      Finally, check with some quite different .exe elsewhere (preferably producing some output), is the behaviour different from with youtube-dl.exe?

                      D Offline
                      D Offline
                      Devolution
                      wrote on last edited by
                      #10

                      @JonB

                      The overload is simply a deprecated one, i can surely try with theirs, nothing happened, still no finished signal.

                      I added a piece of code for the stateChanged signal, here's the output:

                      my state is now: QProcess::Starting
                      my state is now: QProcess::Running
                      STARTED
                      

                      As you suggested i tried with other stuff. Notepad opens notepad as expected.
                      However, gcc, which behave the same without arguments (that is priting a message about no input file) does the exact same thing: goes through starting and running phase, but i'm not able to capture the output nor does it send the finished signal.

                      If i add waitForFinished with the gcc process call, it does put the process in the NotRunning state and fires the event, but still, no output is shown.

                      JonBJ 1 Reply Last reply
                      0
                      • D Devolution

                        @JonB

                        The overload is simply a deprecated one, i can surely try with theirs, nothing happened, still no finished signal.

                        I added a piece of code for the stateChanged signal, here's the output:

                        my state is now: QProcess::Starting
                        my state is now: QProcess::Running
                        STARTED
                        

                        As you suggested i tried with other stuff. Notepad opens notepad as expected.
                        However, gcc, which behave the same without arguments (that is priting a message about no input file) does the exact same thing: goes through starting and running phase, but i'm not able to capture the output nor does it send the finished signal.

                        If i add waitForFinished with the gcc process call, it does put the process in the NotRunning state and fires the event, but still, no output is shown.

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

                        @Devolution
                        Dunno! :( I have used all this stuff and it works OK. Your code looks OK to me. So long as you guarantee your QProcess * ytdl = new QProcess() is not allowing delete ytdl from anywhere after you have called the ytdl->start() :) And, your code does return to the main Qt event loop after the start(), doesn't it?

                        If it were me, this would be bugging me now! Replace your redirection code & readyRead handlers with setStandardOutput/ErrorFile() calls. Send them to separate files/channels, for simplicity. See whether you ever get the output in those files or not....

                        D 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @Devolution
                          Dunno! :( I have used all this stuff and it works OK. Your code looks OK to me. So long as you guarantee your QProcess * ytdl = new QProcess() is not allowing delete ytdl from anywhere after you have called the ytdl->start() :) And, your code does return to the main Qt event loop after the start(), doesn't it?

                          If it were me, this would be bugging me now! Replace your redirection code & readyRead handlers with setStandardOutput/ErrorFile() calls. Send them to separate files/channels, for simplicity. See whether you ever get the output in those files or not....

                          D Offline
                          D Offline
                          Devolution
                          wrote on last edited by
                          #12

                          @JonB

                          Well to be sure i wasn't killing the process anywhere i basically moved its creation in the main just to test the outcome of this 'bug'.

                          This is my 'main.cpp' code

                          
                          
                          int main(int argc, char *argv[])
                          {
                                QApplication app(argc, argv);
                          
                          
                              SoundboardMainUI container;
                          
                              QProcess * ytdl = new QProcess();
                          
                              QObject::connect(ytdl,&QProcess::started, [=]{
                                  qDebug() << "STARTED";
                              });
                              QObject::connect(ytdl, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [=]{
                                  qDebug() << "Youtubedl ended nam";
                                  ytdl->deleteLater();
                              });
                          
                              QObject::connect(ytdl,&QProcess::errorOccurred, [=](QProcess::ProcessError error){
                                  qDebug() << "Error:" << error;
                              });
                          
                              QObject::connect(ytdl, &QProcess::stateChanged, [=](QProcess::ProcessState newState){
                                  qDebug() << "my state is now:" << newState;
                              });
                          
                                    
                              ytdl->setWorkingDirectory(QApplication::applicationDirPath());
                          
                              ytdl->start("gcc");
                          
                          
                          
                              QFile css_dark(":/css/resources/darkorange.css");
                              css_dark.open(QFile::ReadOnly);
                              app.setStyleSheet(css_dark.readAll());
                              css_dark.close();
                          
                                MSG msg;
                                QPixmap pixmap(":/icon/resources/forsenAim.png");
                           
                                app.processEvents();
                           
                                while(GetMessage(&msg,nullptr,0,0))
                                {
                                    TranslateMessage(&msg);
                                    DispatchMessage(&msg);
                                    if (msg.message == WM_HOTKEY)
                                        container.winHotKeyPressed(static_cast<int>(msg.wParam));
                          
                                }
                          
                              // Re-send post quit message or the app runs as a daemon for some reason
                              PostQuitMessage(0);
                          
                              return app.exec();
                          }
                          
                          

                          Trying with output and error files.
                          gcc seems to be correct:

                          //stderr.txt
                          gcc: fatal error: no input files
                          compilation terminated.
                          

                          stdout.txt is empty

                          With youtube-dl.exe:

                          //stderr.txt
                          Usage: youtube-dl.exe [OPTIONS] URL [URL...]
                          
                          youtube-dl.exe: error: You must provide at least one URL.
                          Type youtube-dl --help to see a list of all options.
                          
                          

                          stdout is empty.

                          Once again the output with file is correct...

                          What could be going on ? :/

                          JonBJ 1 Reply Last reply
                          0
                          • D Devolution

                            @JonB

                            Well to be sure i wasn't killing the process anywhere i basically moved its creation in the main just to test the outcome of this 'bug'.

                            This is my 'main.cpp' code

                            
                            
                            int main(int argc, char *argv[])
                            {
                                  QApplication app(argc, argv);
                            
                            
                                SoundboardMainUI container;
                            
                                QProcess * ytdl = new QProcess();
                            
                                QObject::connect(ytdl,&QProcess::started, [=]{
                                    qDebug() << "STARTED";
                                });
                                QObject::connect(ytdl, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [=]{
                                    qDebug() << "Youtubedl ended nam";
                                    ytdl->deleteLater();
                                });
                            
                                QObject::connect(ytdl,&QProcess::errorOccurred, [=](QProcess::ProcessError error){
                                    qDebug() << "Error:" << error;
                                });
                            
                                QObject::connect(ytdl, &QProcess::stateChanged, [=](QProcess::ProcessState newState){
                                    qDebug() << "my state is now:" << newState;
                                });
                            
                                      
                                ytdl->setWorkingDirectory(QApplication::applicationDirPath());
                            
                                ytdl->start("gcc");
                            
                            
                            
                                QFile css_dark(":/css/resources/darkorange.css");
                                css_dark.open(QFile::ReadOnly);
                                app.setStyleSheet(css_dark.readAll());
                                css_dark.close();
                            
                                  MSG msg;
                                  QPixmap pixmap(":/icon/resources/forsenAim.png");
                             
                                  app.processEvents();
                             
                                  while(GetMessage(&msg,nullptr,0,0))
                                  {
                                      TranslateMessage(&msg);
                                      DispatchMessage(&msg);
                                      if (msg.message == WM_HOTKEY)
                                          container.winHotKeyPressed(static_cast<int>(msg.wParam));
                            
                                  }
                            
                                // Re-send post quit message or the app runs as a daemon for some reason
                                PostQuitMessage(0);
                            
                                return app.exec();
                            }
                            
                            

                            Trying with output and error files.
                            gcc seems to be correct:

                            //stderr.txt
                            gcc: fatal error: no input files
                            compilation terminated.
                            

                            stdout.txt is empty

                            With youtube-dl.exe:

                            //stderr.txt
                            Usage: youtube-dl.exe [OPTIONS] URL [URL...]
                            
                            youtube-dl.exe: error: You must provide at least one URL.
                            Type youtube-dl --help to see a list of all options.
                            
                            

                            stdout is empty.

                            Once again the output with file is correct...

                            What could be going on ? :/

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

                            @Devolution said in QProcess and stdout:

                            What could be going on ? :/

                            What's all this

                            app.processEvents();
                            

                            (not so bad) but then horror:

                            while(GetMessage(&msg,nullptr,0,0))
                            

                            ?! :(

                            Get rid of all that Windows-y stuff, test your code as it should be just returning to the main event loop. That must surely be interfering with Qt messages?

                            (E.g. the "process finished" Windows event is getting eaten in the GetMessage() loop? You don't ever exit the GetMessage() loop till quit anyway, so you don't reach app.exec(); till after quit! I don't understand how you're expecting the code to behave, or why you're doing that stuff, and I don't want to know!)

                            Your code will not be what waitForFinished() does, which you have said works. You did not say anything about this, isn't it likely to be relevant? You're also doing your start() before going into app.exec(), do it from within. When you have things working that way correctly, then is the time to re-introduce and play with the code as it is now....

                            D 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @Devolution said in QProcess and stdout:

                              What could be going on ? :/

                              What's all this

                              app.processEvents();
                              

                              (not so bad) but then horror:

                              while(GetMessage(&msg,nullptr,0,0))
                              

                              ?! :(

                              Get rid of all that Windows-y stuff, test your code as it should be just returning to the main event loop. That must surely be interfering with Qt messages?

                              (E.g. the "process finished" Windows event is getting eaten in the GetMessage() loop? You don't ever exit the GetMessage() loop till quit anyway, so you don't reach app.exec(); till after quit! I don't understand how you're expecting the code to behave, or why you're doing that stuff, and I don't want to know!)

                              Your code will not be what waitForFinished() does, which you have said works. You did not say anything about this, isn't it likely to be relevant? You're also doing your start() before going into app.exec(), do it from within. When you have things working that way correctly, then is the time to re-introduce and play with the code as it is now....

                              D Offline
                              D Offline
                              Devolution
                              wrote on last edited by
                              #14

                              @JonB

                              It didn't interfere with any of my signal and slots so i don't think it's the troublemaker here. I tried it tho, and you were right. This windows shenanigans IS actually messing with the stderr and stdout signals.

                              I don' t know if that's expected behavior or not (from windows/qt).

                              The windows-y event loop from windows is there for a reason,as i need it to capture system events: i need capture key stroke, but from everywhere, and not only when the qt application is in focus, which is the behavior QShortcut has, and i didn't find a way native to qt to register "global" shortcuts.

                              Seems i hit a wall there.

                              Could i workaround this using another QEventLoop used just for this process?

                              JonBJ 1 Reply Last reply
                              0
                              • D Devolution

                                @JonB

                                It didn't interfere with any of my signal and slots so i don't think it's the troublemaker here. I tried it tho, and you were right. This windows shenanigans IS actually messing with the stderr and stdout signals.

                                I don' t know if that's expected behavior or not (from windows/qt).

                                The windows-y event loop from windows is there for a reason,as i need it to capture system events: i need capture key stroke, but from everywhere, and not only when the qt application is in focus, which is the behavior QShortcut has, and i didn't find a way native to qt to register "global" shortcuts.

                                Seems i hit a wall there.

                                Could i workaround this using another QEventLoop used just for this process?

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

                                @Devolution
                                You have:

                                while (GetMessage())
                                   ....
                                ...
                                return app.exec();
                                

                                That is a blocking loop, till the user quits. Only then do you allow the Qt main event loop to run (at which point it presumably exits, but that's not relevant). It's not surprising there are problems.

                                I don't know what you want for what you want to achieve, but clearly this interferes with your process reading/finishing. A very knowledgeable Qt expert better than me suggests you look at https://doc.qt.io/qt-5/qabstractnativeeventfilter.html ... :)

                                D 1 Reply Last reply
                                0
                                • JonBJ JonB

                                  @Devolution
                                  You have:

                                  while (GetMessage())
                                     ....
                                  ...
                                  return app.exec();
                                  

                                  That is a blocking loop, till the user quits. Only then do you allow the Qt main event loop to run (at which point it presumably exits, but that's not relevant). It's not surprising there are problems.

                                  I don't know what you want for what you want to achieve, but clearly this interferes with your process reading/finishing. A very knowledgeable Qt expert better than me suggests you look at https://doc.qt.io/qt-5/qabstractnativeeventfilter.html ... :)

                                  D Offline
                                  D Offline
                                  Devolution
                                  wrote on last edited by
                                  #16

                                  @JonB

                                  Oh thanks, i never found this event filter thing. I'll try to play around with it and replace the sketchy windows loop. If i can render this more platform-agnostic i'd be happy.

                                  Thanks to you and your friend :) I'll mark this as resolved

                                  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