Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Is it possible to send answer to cmd by QT?



  • Many Times I used cmd I have to answer the question ( sometimes yes / no, sometimes other words ). How to send some words by QProcess?


  • Lifetime Qt Champion

    Hi
    Your description is a bit vague.
    You can add parameters to the call of the other .exe but
    unless the .exe directly supports it, you cannot set predefined answers to any questions it might ask.


  • Qt Champions 2019


  • Lifetime Qt Champion

    @jsulm
    so if you call write in the right order, it will be used correctly for the interactive process?


  • Qt Champions 2019

    @mrjj I would first wait for readyRead, check whether I get the input mask (like "Press Y/N" or what ever the console app writes) and then write. Then the order should be correct.


  • Lifetime Qt Champion

    @jsulm
    ah. so its possible to make small state machines and use write to answer.
    cool. I didn't know write could be used that way.



  • @jsulm @mrjj
    I have 2 apps:
    The first of them:

    #include <QCoreApplication>
    #include "iostream"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        string answer;
    
        cout<<"Do you prefer forest or sea?";
    
        cin>>answer;
        if(answer == "forest")
        {
            cout<<"You prefer forest!";
        }
        else if(answer == "sea")
        {
            cout<<"You prefer sea!";
        }
        else
        {
            cout<<"This answer is bad!";
        }
        exit(0);
        return a.exec();
    }
    

    The second one:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        QProcess proc;
        proc.start(R"(C:\Users\tom\Desktop\app\consoleApp.exe)");
        proc.waitForStarted();
        
        while(proc.waitForReadyRead())
            qDebug()<<proc.readAll();
        proc.write("sea");
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    I tried using "write", but with no positive result.

    I also tried:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        QProcess proc;
        proc.start(R"(C:\Users\tom\Desktop\app\consoleApp.exe)");
    
        proc.waitForReadyRead();
        qDebug()<<proc.readAllStandardOutput();
        proc.write("sea");
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    

    But I get "QProcess: Destroyed while process ("C:\Users\tom\Desktop\app\consoleApp.exe") is still running."


  • Lifetime Qt Champion

    Hi,

    proc is local to the constructor, it's destroyed right after your call to write and your other app is still running hence the error message.



  • @SGaist Exactly.

    I change it and now my code looks like:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        
        proc = new QProcess;
        connect(proc, SIGNAL(readyRead()), this, SLOT(text()));
        proc->start(R"(C:\Users\tom\Desktop\app\consoleApp.exe)");
        proc->waitForStarted();
        proc->waitForReadyRead();
    
        proc->write("sea");
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::text()
    {
        qDebug()<<proc->readAllStandardOutput();
    }
    

    I still don't get the information that I prefer sea.


  • Lifetime Qt Champion

    You are mixing the blocking and non blocking API which is a bad idea.

    Do either but not both.



  • @SGaist I change code :)

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        proc = new QProcess;
        proc->start(R"(C:\Users\tom\Desktop\app\consoleApp.exe)");
        proc->waitForStarted();
        proc->waitForReadyRead();
        qDebug()<<proc->readAllStandardOutput();
        proc->write("sea");
        
        qDebug()<<"I see you";
        proc->waitForReadyRead();
        qDebug()<<proc->readAllStandardOutput();
        qDebug()<<"I don't see you";
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    

    But still don't see that answer. I don't see "I don't see you" text too.


  • Lifetime Qt Champion

    Maybe because the signal is not emitted. Since the application ends after writing to cout, you can use waitForFinished and then read its output.



  • I give up... Please for snippet :)



  • @TomNow99
    I think: assuming you do see "I see you" but you do not see "I don't see you", then replace the second occurrence of

    proc->waitForReadyRead();
    

    by

    proc->waitForfinished();
    


  • @JonB

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
            proc = new QProcess;
            proc->start(R"(C:\Users\tom\Desktop\app\consoleApp.exe)");
            proc->waitForStarted();
            proc->waitForReadyRead();
            qDebug()<<proc->readAllStandardOutput();
            proc->write("sea");
    
            qDebug()<<"I see you";
            proc->waitForFinished();
            qDebug()<<proc->readAllStandardOutput();
            qDebug()<<"I don't see you";
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    I change the second "waitForReadyRead". But still I don't see " I don't see" ( I see but after 30 seconds - I think the 30 seconds is a time when proc is terminate ).


  • Lifetime Qt Champion

    Then you should add some error checking in your code.



  • @jsulm Could you look at my code and told me what I have to change?


  • Qt Champions 2019

    @TomNow99 Besides what @SGaist suggested, what does first "qDebug()<<proc->readAllStandardOutput();" output?



  • @SGaist @jsulm @JonB @mrjj

    I add to my second App slots and a few changes like this ( I don't change consoleApp ):

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        proc = new QProcess;
        connect(proc, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(stateChangedSlot(QProcess::ProcessState)));
        connect(proc, SIGNAL(finished(int , QProcess::ExitStatus )), this, SLOT(finishedSlot(int , QProcess::ExitStatus )));
        connect(proc, SIGNAL(errorOccurred(QProcess::ProcessError )), this, SLOT(errorOccurredSlot(QProcess::ProcessError )));
    
        proc->start(R"(C:\Users\tom\Desktop\app\consoleApp.exe)");
        proc->waitForStarted();
        proc->waitForReadyRead();
        qDebug()<<proc->readAllStandardOutput();
        proc->write("sea");
        qDebug()<<"I see you";
        proc->waitForReadyRead();
        qDebug()<<proc->readAllStandardOutput();
        qDebug()<<"I don't see you";
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::stateChangedSlot(QProcess::ProcessState state)
    {
        qDebug()<<"From stateChangedSlot: "<<state;
    }
    
    void MainWindow::finishedSlot(int exitCode, QProcess::ExitStatus exitStatus)
    {
        qDebug()<<"From finishedSlot: "<<exitCode<<exitStatus;
    }
    
    void MainWindow::errorOccurredSlot(QProcess::ProcessError error)
    {
        qDebug()<<"From errorOccuredSlot: "<<error;
    }
    
    

    The output from qDebug() is:

    From stateChangedSlot:  QProcess::Starting
    From stateChangedSlot:  QProcess::Running
    "Do you prefer forest or sea?"
    I see you
    ""
    I don't see you
    

    First I get:

    From stateChangedSlot:  QProcess::Starting
    From stateChangedSlot:  QProcess::Running
    "Do you prefer forest or sea?"
    I see you
    

    Next I wait 30 seconds ( this is default value for waitForReadyRead ) and I get:

    ""
    I don't see you
    

    And qMainWindow change state to visible.

    Then I close my Application because nothing to do.



  • @TomNow99
    For my part at least, I struggle to understand what the issue is, because we don't see what consoleApp.exe does/is supposed to do/how it is written, and you don't actually tells us what the expected behaviour is versus what happens in your output shown.

    So what is the actual problem? Please state clearly & concisely.

    Are you saying consoleApp.exe is supposed to see the proc->write("sea"); and respond to it? Or quit? Or what? How do we know what it expects, e.g. do you need to send a \n on the end of that string??

    EDIT Ah, I see now. I think you said at the start it has code cin>>answer;. You would have to look it up, but doesn't that have to wait for either a \n terminator or end-of-file before that returns? Is that all your problem is? When you test that app from the console, don't you have to type the Enter key after the word before it responds? Also, I am unclear how the QProcess channel works text-wise on Windows, you might want to append \r\n instead of just \n to your string.

    I'm not a great fan of the QProcess::waitFor...() blocking calls. You might be better using signals/slots for the whole thing, like you have done for the three slots you have so far.



  • @JonB I added code consoleApp.exe ( look at my second post which is started "I have 2 apps:" ). Of course I add this code in this post too:

    #include <QCoreApplication>
    #include "iostream"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        string answer;
    
        cout<<"Do you prefer forest or sea?";
    
        cin>>answer;
        if(answer == "forest")
        {
            cout<<"You prefer forest!";
        }
        else if(answer == "sea")
        {
            cout<<"You prefer sea!";
        }
        else
        {
            cout<<"This answer is bad!";
        }
        exit(0);
        return a.exec();
    }
    

    I would like to start consoleApp.exe from my mainApp.exe, get the question "Do you prefer forest or sea?" from consoleApp.exe, send the answer "sea" to consoleApp.exe from mainApp.exe, get the output "You prefer sea!" from consoleApp.exe.



  • @TomNow99
    Your reply has crossed with my seeing the earlier code, which I think you have just added? You see that we need to see that in order to have a clue what is going on! Please read the EDIT section of my post above, I think that's all your problem is.



  • When I add "\n" to write

    proc->write("sea\n");
    

    everything works!

    Thank you all @mrjj @jsulm @SGaist @JonB


Log in to reply