Qt Execute external program - c++

I want to start an external program out of my QT-Programm. The only working solution was:
system("start explorer.exe");
But it is only working for windows and starts a command line for a moment.
Next thing I tried was:
QProcess process;
QString file = QDir::homepath + "file.exe";
process.start(file);
//process.execute(file); //i tried as well
But nothing happened. Any ideas?

If your process object is a variable on the stack (e.g. in a method), the code wouldn't work as expected because the process you've already started will be killed in the destructor of QProcess, when the method finishes.
void MyClass::myMethod()
{
QProcess process;
QString file = QDir::homepath + "file.exe";
process.start(file);
}
You should instead allocate the QProcess object on the heap like that:
QProcess *process = new QProcess(this);
QString file = QDir::homepath + "/file.exe";
process->start(file);

If you want your program to wait while the process is executing and only need to get its exit code, you can use
QProcess::execute(file);
QProcess::exitCode(); // returns the exit code
instead of using process asynchronously like this.
QProcess process;
process.start(file);
Note that you can also block execution until process will be finished. In order to do that use
process.waitForFinished();
after start of the process.

QDir::homePath doesn't end with separator. Valid path to your exe
QString file = QDir::homePath + QDir::separator + "file.exe";

Just use QProcess::startDetached; it's static and you don't need to worry about waiting for it to finish or allocating things on the heap or anything like that:
QProcess::startDetached(QDir::homepath + "/file.exe");
It's the detached counterpart to QProcess::execute.
As of 5.15 that form is obsolete (but still present). The new preferred call is the same as the above but with a QStringList of command line arguments as the second parameter. If you don't have any arguments to pass just pass an empty list.

Related

QProcess Backup Database on QT C++

I want to backup my database with qprocess in QT program, the code is as follows, but 0kb occurs when backing up and when I look at the error Qprocess: Destroyed while process("mysqldump.exe") is still runnuing.
QProcess dump(this);
QStringlist args;
QString path="C:/Users/mahmut/Desktop/dbbackupfile/deneme.sql";
args<<"-uroot"<<"-proot"<<"kopuz"<<">";
dump.setStandardOutputFile(path);
dump.start("mysqldump.exe",args);
if(!dump.waitForStarted(1000))
{
qDebug()<<dump.errorString();
}
Can you help to me? ı do not understand this error and okb back up file.
Your program terminates before process finished, you need to either use static bool QProcess::startDetached(program, arguments, workingDirectory) or add dump.waitForFinished(); to the end.
Also, you dont need to add ">" to arguments. You already redirected output with dump.setStandardOutputFile(path), ">" does not work with process as it requires shell to execute command, QProcess does not use shell it just runs one process not shell expression.

How do I keep a command executed by QProcess when the process ends?

I'm trying to find a way to keep the commands executed by QProcess after GUI program is terminated in Linux system. Now, when the process ends, all the commands executed are gone. Is there a way to keep that after QProcess is terminated?
// code which executes command in linux
QProcess *mproc = new Qprocess(this);
QStringList args;
mproc->setWorkingDirectory("/home/test");
args << "-c" << "source tool_def1.env; source tool_def2.env; myProg";
mproc->start("/bin/csh", args);
The tool_def1.env and tool_def2.env file are included some environment variables for executing myProg, like set path = (~~~~).
In GUI Program, this code is well done. And, I want to execute myProg program in terminal which GUI program is run after GUI program is terminated.
But, if GUI Program is terminated, I can't run myProg because the environment variables of tool_def1.env and tool_def2.env file is disappear.
Is it possible to keep the environment variables? Or, is it possible to execute myProg program in other process with environment variables of mproc process as following?
QProcess *mproc2 = new QProcess(this);
mproc2->setWorkingDirectory("/home/test2");
mproc2->start("myProg");
The overload of QProcess::startDetached you are using is a static method, so it will not take into consideration attributes of particular instances, i.e., mproc->setWorkingDirectory("/home/test") doesn't set the working directory for the static method, only for mproc. When you launch the process, as the working directory is not set for the static call, the program cannot be found and it fails.
As you can see in the documentation, the static startDetached also admits the working directory as a parameter, so you can change your code to:
QStringList args;
args << "-c" << "source tool_def1.env; source tool_def2.env; myProg";
QProcess::startDetached("/bin/csh", args, "/home/test");
Another way is using the non-static version, which requires the program to be specified separately:
QProcess mproc(this);
QStringList args;
args << "-c" << "source tool_def1.env; source tool_def2.env; myProg";
mproc.setArguments(args);
mproc.setWorkingDirectory("/home/test");
mproc.setProgram("/bin/csh");
qint64 pid; // to store the process ID (will become invalid if the child process exits)
mproc.startDeatached(&pid);
Regarding your second question, take a look at QProcess::setProcessEnvironment. Just that you'll have to use the non-static way to set the environment of the process. You can get the environment variables of the current process using QProcess::systemEnvironment.
mproc.setProcessEnvironment(QProcess::systemEnvironment());
Update from comments: if you want to always use the environment variables active when the GUI application was running (is it some kind of configurator?) you can just save them to a file (a JSON for example), then load and set them manually from the second process.
To extract them, you can do something like:
const auto env_vars = QProcess::systemEnvironment().toStringList();
Now env_vars will be a list of strings with format NAME_OF_ENVAR=VALUE_OF_ENVAR. You can save such list to the file (you will need to prepend an export at the beginning of each line to be usable with source).
I've tested the static version in Windows (VS 15.8.2 and Qt 5.10.0) and it worked as expected. Code used:
#include <qprocess.h>
int main(int argc, char* argv[])
{
QProcess::startDetached("cmd", QStringList() << "/c" << "test.exe", "../test/");
return 0;
}
where test.exe's code is basically a never ending process.
Note: An interesting fact, and as a note for developer using VS. For the same program and build, if it is executed from the command line it works correctly: application ends and the second process keeps running in the background, but if executed from the VS IDE then the console window keeps alive, and if I close it, the the second process is killed too. When debugged, the debugger ends but the console is still shown. I suppose it is because VS somehow tracks all created processes when launched from the IDE.

Qt QProcess how to write to standard in?

I am starting a QProcess to open cmd.exe.
I want to write to std in to send commands to cmd.exe, and I want to recieve it's output.
QProcess mProcess = new QProcess(this);
mProcess->setReadChannelMode(QProcess::SeparateChannels);
mProcess->start("cmd");
QApplication::processEvents();
QString s(mProcess->readAllStandardOutput());
writeToConsole(s);
This all works just fine. The process starts, I get output. However, I can't now write to the process anymore. I have looked over QProcess documentation and I don't see any way to write to standard in. I've tried mProcess->write(data); but that didn't do anything.
How do I write to standard in to the running process?
You have to use write function only to write in to the standard in.
But the important thing is you have to close the write channel using void QProcess::closeWriteChannel().
Look into below documentation.
http://doc.qt.io/qt-5/qprocess.html#closeWriteChannel
You should wait for operations to finish before moving on to the next action.
QProcess mProcess = new QProcess(this);
mProcess->setReadChannelMode(QProcess::SeparateChannels);
//Start the process
mProcess->start("cmd");
QApplication::processEvents();
mProcess->waitForStarted();
// Read the output
mProcess->waitForReadyRead();
QString output(mProcess->readAllStandardOutput());
mProcess->closeReadChannel();
// Write the data
mProcess->write(output);
mProcess->waitForBytesWritten();
mProcess->closeWriteChannel();
// Wait for finished
mProcess->waitForFinished();
It seems strange to send the output directly back into the program being executed. Alternatively you could connect the void QIODevice::readyRead() signal to a slot where the output can be handled elsewhere.
The mistake I was making here was not putting \n on the end of the multiple commands.
''''
// 1st command
mProcess->write(output1 + "\n");
mProcess->waitForBytesWritten();
// 2nd command
mProcess->write(output1 + "\n");
mProcess->waitForBytesWritten();
// Wait for finished
mProcess->waitForFinished();
mProcess->closeWriteChannel();
''''

Monitor running qprocess and return value when qprocess is finished

I want to run a qprocess (the program adb) and when the process is finished return the results to the calling function. However, there's every possibility that adb could find itself in a loop, printing error messages such as "ADB server didn't ACK" to stdout, not ever finishing. I need to trap these errors.
QProcess run_command;
connect(&run_command,SIGNAL(readyReadStandardOutput()),this,SLOT( dolog() ));
QString result=RunProcess("adb connect 192.168.1.100");
...
QString MainWindow::RunProcess(QString cstring)
{
run_command.start(cstring);
// keep gui active for lengthy processes.
while(run_command.state() != QProcess::NotRunning)
qApp->processEvents();
QString command=run_command.readAll();
return command; // returns nothing if slot is enabled.
}
void MainWindow::dolog()
{
QString logstring = run_command.readAllStandardOutput();
if (logstring.contains("error condition")
logfile("Logfile:"+logstring);
}
If I enable the signal/slot, dolog() prints stdout to a logfile, but RunProcess returns a blank string. If I disable the signal/slot, RunProcess() returns the qprocess output as expected.
First you need to identify which output stream the command in question is using for its errors.
It is very like stderr so you would need to connect to the readyReadStandardError() signal instead.
For the command itself I would recommend to split it into command and arguments and use the QProcess::start() overload that takes the command and a list of arguments.
Just more robust than to rely on a single string being correctly separated again.

What is the difference between QProcess::start and QProcess::startDetached?

The Qt documentation gives this explanation:
QProcess::start:
Starts the given program in a new process, if none is already running,
passing the command line arguments in arguments.
QProcess::startDetached:
Starts the program program with the arguments arguments in a new
process, and detaches from it.
What is the difference between the two? Is the difference only that you can start just one instance of a program using QProcess::start and many instances using QProcess::startDetached?
If you use start, termination of the caller process will cause the termination of the called process as well. If you use startDetached, after the caller is terminated, the child will continue to live. For example:
QProcess * p = new QProcess();
p->start("some-app");
delete p;// <---some-app will be terminated
QProcess * p = new QProcess();
p->startDetached("some-app");
delete p;// <---some-app will continue to live
The start() function is a member function, while startDetached is a static class function.
If you look at the documentation of QProcess, you'll see that there are functions to allow you to do things with the process such as: -
Receive the output or error streams from the running process (readAllStandardOutput / readAllStandardError)
Redirect the output to a file (setStandardOutputFile)
Use a file for standard input into the process (setStandardInputFile)
Communicate via channels
Get notified when the process has finished
These are just some of the things that you can only do with an instance of a QProcess. If, however, you want a simple and quick way of starting a process without having to create an instance and you don't need the extra functionality, you can simply call QProcess::startDetached.
Also, as the docs state for startDetached: -
If the calling process exits, the detached process will continue to live.