How to start a process in Windows using QT? - c++

I'm trying to start a console application on Windows using QProcess's method 'start'. Official documentation says I can do it like this:
QProcess process;
process.start("C:/Windows/System32/cmd.exe");
I expect that a standard greeting message will appear in the calling application's console, but this does not happen, though the called process is running. What is wrong here?

use of bellow example :
QProcess *process = new QProcess(this);
QString program = "explorer.exe";
QString folder = "C:\";
process->start(program, QStringList() << folder);
also you can use of system() as bellow :
system("C:/Windows/System32/cmd.exe");

How about this static call?
QProcess::startDetached(FilePath,Arguments,StartInDir);
No need to create any objects!

Related

How to run Python script from QT creator and print output to GUI

void MainWindow::on_pushButton_clicked()
{
QProcess p;
// get values from ini file
settings->setValue("EMail", ui->lineEditEMail->text());
settings->setValue("Password", ui->lineEditPassword->text());
settings->setValue("Chronological", ui->checkBox->isChecked());
settings->setValue("Current_info", ui->checkBox_2->isChecked());
settings->endGroup();
settings->sync();
// launch python code for login
QString program( "C:/projects/build-test3-Desktop_Qt_6_4_0_MinGW_64_bit-Debug/venv/Scripts/python.exe");
QStringList args = QStringList() << "index.py";
QProcess::execute( program, args );
}
I have this function that is executed after a button is clicked and I need to print the output of "index.py" in to my app. What widget should I use and how? From what I read QTextBrowser should do the trick but I'm not sure how to use it.
This is how my GUI looks like. I'd like to use to output my results somewhere in button right. I didn't add the widget yet, because I'm not sure QTextBrowser is the one I need
The widget you could use for this purpose is QTextEdit (you can set it to be read-only from the graphical user interface).
But if you want to get the output of the execution, you will need a proper instance of QProcess and call the QProcess::readAllStandardOutput() member function to get the standard output.
You may also be interested by QProcess::readAllStandardError() to get the errors in case of failure.
Edit (simple/basic example):
QProcess p;
p.start("path/to/python.exe", QStringList("script.py"));
p.waitForFinished();
QByteArray p_stdout = p.readAllStandardOutput();
QByteArray p_stderr = p.readAllStandardError();
// Do whatever you want with the results (check if they are not empty, print them, fill your QTextEdit contents, etc...)
Note: If you don't want to be blocking with QProcess::waitForFinished(), you can use a signal/slots connection on QProcess::finished() signal.

showing cmd terminal in qt widgets application

I'm trying to pass some cmd commands using system() and I would like to be able to "communicate" with cmd, say I code in system("dir") in my mainwindow.cpp under my clicked function
this is what it looks like for example
void MainWindow::on_pushButton_login_clicked()
{
std::string platform_server_ip = ui->lineEdit_platform_server_ip->text().toStdString();
if (platform_server_ip == "dir"
{
QMessageBox::information(this,"Login", "all required log in details are correct");
close();
const char* c = platform_server_ip.c_str();
system(c);
system("ipconfig");
}
I would like to know why it behaves like this and if that's normal. I've included CONFIG += console
in my project file, and checked "run in terminal" (tried it also without) but it never shows me my desired outcome.
Instead what I get, is a blank terminal that pops up along side my GUI, and then when I enter "dir" in my GUI and hit enter, a cmd window pops up really fast and in less than a second, its gone. I've even tried it with system("ipconfig")andsystem ("pause")
as well as with one system command like this system("ipconfig" "&pause")
desired outcome: is just a normal execution of system("ipconfig"), followed by other system commands, that display the same result as typing them in cmd itself.
I've also tried all this in "qt Console application" and I either get the same result, or the output (what would normally be as output on cmd) is then found in "application output" of qt creator.
Is there another better way I can achieve what I want?
I'm truly a noob and would really appreciate some guidance.
You can try
system("cmd /k ipconfig");
This will open another terminal window which will stay open (k stands for keep) at the end of the command execution.
I think you don't need the CONFIG += console project setting, to achieve this. Calling system will start another process, which isn't related at all with the calling application.
If you want to start external programs from within a Qt application, you can use QProcess class, which lets you somehow interact with the started processes through standard in/out. For a very simple example, have a form with a push button and a text edit called textEdit; in the push button clicked slot:
QProcess process;
process.start("ipconfig");
process.waitForReadyRead();
ui->textEdit->setText(process.readAll());
process.waitForFinished();
This way, you won't see additional console windows, and the command output will be shown directly in your text edit.
This can be generalized in a function like this:
bool exec(QString command)
{
QProcess process;
process.start(command);
if(!process.waitForStarted())
{
return false; //the process failed to start
}
//etc...
return true;
}
Depending on whether this is not just a quick hack/tool, you can look at QProcess for more indepth control over your process so that you can read / write the child process pipes.

Redirecting the output of QProcess when running a resource file

fairly new to Qt.
I'm using QProcess to run an external shell script and redirecting the output to a textBrowser on my GUI. Code:
In mainwindow.h:
private:
QProcess *myProcess;
and mainwindow.cpp:
void MainWindow::onButtonPressed(){
myProcess = new QProcess(this);
myProcess->connect(myProcess, SIGNAL(readyRead()), this, SLOT(textAppend()));
myProcess->start("./someScript.sh", arguments);
}
void MainWindow::textAppend(){
ui->textBrowser->append(myProcess->readAll());
}
This works perfectly to run an external script. My question is how to apply the same process with the script included as a resource file.
I've tried simply replacing "./someScript.sh" with the resource version ":/someScript.sh" but it does not seem to work.
The resource script runs perfectly, but the console output disappears.
For this reason, there is something called "QTemporaryFile" class.
Because you need to call a file that already exists in your system - ok!
let's take this example :
using QProcess we need to run a python file from resource
//[1] Get Python File From Resource
QFile RsFile(":/send.py");
//[2] Create a Temporary File
QTemporaryFile *NewTempFile = QTemporaryFile::createNativeFile(RsFile);
//[3] Get The Path of Temporary File
QStringList arg;
arg << NewTempFile->fileName();
//[4] Call Process
QProcess *myProcess = new QProcess(this);
myProcess->start("python", arg);
//[5] When You Finish, remove the temporary file
NewTempFile->remove();
Note : on windows, the Temporary File stored in %TEMP% directory
and for more informations you can visit Qt Documentation - QTemporaryFile Class
Good Luck ♥
I does not work because when you run myProcess->start(":/someScript.sh", arguments); you ask your system to run :/someScript.sh which does not exist for your system.
A quick solution would be to copy the script to a temporary folder and run it from there.
QFile::copy(":/someScript.sh", pathToTmpFile);
myProcess->start(pathToTmpFile, arguments);
I would also suggest you make use of QTemporaryFile to get a unique temporary file name.

QT Creator QProcess

I want to run a fortran executable that is called when I click in push button in the interface that I created.
Although when I click in the button nothing happens. Here is the code:
QProcess *process = new QProcess(this);
QString program = QDir::currentPath() + "/PARROT/Console1.exe";
process->start(program);
The string is in that way because I want to be capable of changing the path to the main executable and the fortran executable.
What I'm doing wrong?
Check this link - QProcess Start command syntax
syntax - void QProcess::start(const QString & program, const QStringList & arguments, OpenMode mode = ReadWrite)
You need to pass the argumentlist as 2nd parameter,along with the process path as 1st parameter, needed to start the process.

Display QProcess output in another window

I'm using the QT Creator on Ubuntu.
I have GUI with a mainwindow and another window called "progress".
Upon clicking a button the QProcess starts and executes an rsync command which copies a folder into a specific directory. I created a textbrowser which reads the output from the rsync command. Also clicking the button causes the "progress" window to pop up.
So far so so good, now my problem.
Instead of showing the rsync output in my mainwindow i want it to be in progress.
I've tried several methods to get the QProcess into the progress via connect but that doesn't seem to work.
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
if (ui->checkBox->isChecked()
)
m_time ="-t";
QObject parent;
m_myProcess = new QProcess();
connect(m_myProcess, SIGNAL(readyReadStandardOutput()),this, SLOT(printOutput()));
QString program = "/usr/bin/rsync";
arguments << "-r" << m_time << "-v" <<"--progress" <<"-s"
<< m_dir
<< m_dir2;
m_myProcess->start(program, arguments);
}
progress.cpp
void Progress::printOutput()
{
ui->textBrowser->setPlainText(m_myProcess->readAllStandardOutput());
}
I know it's pretty messy iv'e tried alot of things and haven't cleaned the code yet also I'm pretty new to c++.
My goal was to send the QProcess (m_myProcess) to progress via connect but that didn't seem to work.
Can you send commands like readyReadAllStandardOutput via connect to other windows (I don't know the right term )?
Am I doing a mistake or is there just another way to get the output to my progress window ?
m_myProcess is a member of the class MainWindow and you haven't made it visible to the class Progress. That's why you have the compilation error
m_myProcess was not declared in this scope
What you could do:
Redirect standard error of m_myProcess to standard output, such that you also print what is sent to standard error (unless you want to do something else with it). Using
m_myProcess.setProcessChannelMode(QProcess::MergedChannels);
Make the process object available outside MainWindow
QProcess* MainWindow::getProcess()
{
return m_myProcess;
}
Read the process output line by line in Progress. It needs to be saved in a buffer because readAllStandardOutput() only return the data which has been written since the last read.
... // somewhere
connect(window->getProcess(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput())
...
void Progress::printOutput(){
//bigbuffer is member
bigbuffer.append(myProcess->readAllStandardOutput();)
ui->textBrowser->setPlainText(bigbuffer);
}