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

Using QProcess to Create Mock Command Prompt



  • Hi everyone! My goal is to create an embed mock command prompt, so users can ssh into various machines. Basically, the command prompt has a box for the command information (including all errors and output), a smaller box where the user can type the command, and a push button to execute that command. Please see image below:

    396b0b6c-a532-41ef-b96b-6a2e3e8d5006-image.png

    When the enter button is clicked, the following function is executed:

    void MainWindow::on_enterButton_clicked()
    {    
       command = new QProcess(this);
    
        QString program = ui->command->text();
        QCoreApplication::processEvents();
    
        //connect the signals for output and error
        connect(command, SIGNAL(readyReadStandardError()), this, SLOT(updateError()));
        connect(command, SIGNAL(readyReadStandardOutput()), this, SLOT(updateText()));
        command->start(program);
    
        ui->commandPrompt->appendPlainText("\n\n |-------------------------------------------------");
        ui->commandPrompt->appendPlainText("COMMAND>"+ui->command->text());
    
        ui->command->setText("");
    }
    

    Here are the slot functions called by that function:

    void MainWindow::updateError()
    {
        QByteArray data = command->readAllStandardError();
        ui->commandPrompt->appendPlainText(QString(data));
    }
    
    void MainWindow::updateText()
    {
        QByteArray data = command->readAllStandardOutput();
        ui->commandPrompt->appendPlainText(QString(data));
    }
    

    The major problem I am having is related to commands that require the user to respond to the terminal. Here are two examples:

    1. When using the ssh command, sometimes the user is prompted to input additional information. How can I get the command to output this prompt and allow the user to respond? I found the note in the documentation that says to "execute the command interpreter itself (cmd.exe on some Windows systems), and ask the interpreter to execute the desired command", but I am unsure how to accomplish this.
    2. With the cd command, the change in directory does not work, and all future commands are executed in the same original directory.

    If anyone has any advice, that would be greatly appreciated. Thanks!


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    One issue you have is that you create a new QProcess for each and every command (and since you don't delete them, you are filling your memory with them) so each command you send is executed in a new prompt. You likely have to use the standard input, output, and error channel that are provided by QProcess. You also have to start it once and then use the IO methods to send and receive data to the process.



  • Thank you for your reply! I appreciate your help.

    I understand the concept of what you are saying, and I know that I need to get the output of that command and display that to the user. I am using only the output and error channels right now, so perhaps I need to incorporate the input section. However, I am unsure how, since the need for additional input from the user is not shown in the output nor error streams. Do you have any suggestions/documentation that may be able to help me tackle this? Thanks!



  • @cstevenson said in Using QProcess to Create Mock Command Prompt:

    1. With the cd command, the change in directory does not work, and all future commands are executed in the same original directory.

    What cd command?

    Do you mean: you allow the user to type cd, you use QProcess to execute that, and then you're surprised to find your app, and any commands the user subsequently types which you execute, have retained the original current directory? Running cd in a sub-process has no effect after that sub-process finishes. You will need your app to "remember" when the user cds, and set that resulting directory for future QProcesses you spawn. See https://doc.qt.io/qt-5/qprocess.html#setWorkingDirectory.

    You will also have to do something similar for a whole bunch of potential commands you might allow the user to type, which are internal to the shell and will "disappear" after you have executed them but you wish to persist. For example, if you need to allow the user to go set ENVIRONMENT_VARIABLE=value and that is to affect subsequent commands, you would need to "remember" these too, here for https://doc.qt.io/qt-5/qprocess.html#setProcessEnvironment. I don't know what range of commands you intend the user to perform, but if you're not careful you will end up needing to implement a pseudo-command-interpreter-code of your own....


  • Lifetime Qt Champion

    You can call write on the QProcess instance.



  • @SGaist I am still not able to get this working properly. I set up a single instance of the command prompt as a QProcess. I am receiving the following error when using the write function: "QWindowsPipeWriter::write failed. (The handle is invalid.)". Have you encountered this error before? Thanks!



  • @cstevenson
    Show your code, both for the command you are running and your in/out connections. I don't know whether you will be able to successfully drive Windows Command Prompt this way.


  • Qt Champions 2019

    @cstevenson Please also connect a slot to https://doc.qt.io/qt-5/qprocess.html#errorOccurred
    The process is probably not running when you call write().