I am trying to start external programs and to communicate with them.
I want to run this application in background using QProcess. And also pass commands as well from this code to this process.
Can someone throw light on this and direct me accordingly to execute commands as well when code is running.
Something like this in python but for c++ using QProcess
p = subprocess.Popen(['mpg321', '-R', 'anyword'], stdin=PIPE)
p.stdin.write('LOAD test.mp3\n')
Try this:
QProcess subprocess;
subprocess.start("mpg321", QStringList() << "-R" << "anyword");
if (!subprocess.waitForStarted())
return false;
subprocess.write("LOAD test.mp3\n");
Related
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.
In my QT widget application I am attempting to run a shellscript that opens a C++ program and provides inputs to the program as well. The program starts a command prompt that requires the users input to start. Once the program is started the output of the program is redirected via the standard output to a text file. I am attempting to use QProcess to open and run this shellscript, then read the standard output that is being used to print the result of the C++ program to the text file. The shell script only runs this process and does not terminate it. This is because I need to continuously read this output into the GUI as the program is running. It will not be sufficient to wait until the program is finished to read this information. I am fairly new to QT and C++ programming. I was hoping that someone could help me with my implementation of this.
QProcess process;
process.start("/home/pi/Desktop/ShellScripts/RunTutorial3.sh");
QString output =process.readAllStandardOutput();
qDebug() << output;
QString err = process.readAllStandardError();
qDebug() << err;
I have experimented with using other read function such as readline and also trying to start the process as a detatched process. I have not had success with any of my experimentations. Is it possible to do what I am attempting in QT. I just need the program to run continuously and for QT to read this output every so often.
Shell script:
#!/bin/bash
cd
cd Desktop
cd tutorial3App
cd bin
echo "start" | ./tutorial3
C++ code: I need the meanTOE value to be captured in standard output to use in my GUI.
/ Calculate average time to end of discharge
double meanToE = std::accumulate(ToESamples.begin(), ToESamples.end(), 0.0)/ToESamples.size();
file << ": EOL in " << meanToE << " s" << std::endl;
As I said in my comments one of the main problems is that when you run tutorial3 that process is separated so you can not get the output. Therefore, I recommend executing it directly, and QProcess is probably a local variable, eliminating after printing an empty text, a possible solution is to create a pointer. Another improvement would be to use the readyReadStandardOutput and readyReadStandardError signals since the impressions are not automatic.
QProcess *process = new QProcess(this);
connect(process, &QProcess::readyReadStandardOutput, [process, this](){
QString output =process->readAllStandardOutput();
qDebug() << "output: "<< output;
});
connect(process, &QProcess::readyReadStandardError, [process](){
QString err = process->readAllStandardError();
qDebug() << "error: "<<err;
});
process->setWorkingDirectory("/home/pi/Desktop/tutorial3App/bin/")
process->start("tutorial3", QStringList() << "start");
I think you have to read about signals and slots in Qt. QProcess has got a signal readyReadStandardOutput. So you have to connect to this signal and in your slot you should use QProcess function readAllStandardOutput. In other words when your shell programm outputs something you catch it in your slot and dump it or whatever you want.
Check the answer on this question. It might help you.
reading and writing to QProcess in Qt Console Application
I am working in Qt 4.7, and I have a program that needs to use a QProcess to output the result of running a Windows PowerShell command. For the purposes of this question, let's say all that needs to be supported is use of the "-Command" option. Right now I have this:
QString path = "C:/windows/system32/WindowsPowerShell/v1.0/powershell.exe";
QStringList command;
command.append("-Command");
command.append(/*Whatever test command I want to use...*/);
process = new QProcess(); //Note: QProcess *process is a member of this class
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(/*slot to print qprocess errors...*/);
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(/*slot to display PowerShell output...*/);
process->start(path, command);
The slot to print the PowerShell output is simply as follows:
std::cout << "RESULT: " << QString(process->readAllStandardOutput()).toStdString() << std::endl;
This works perfectly with correct PowerShell commands. For example, I tested it with the command "Get-ChildItem C:\", and it printed the correct data. It also works fine if there is a QProcess error. What I need to know how to do is, how can I have it print a PowerShell error message? For example, if I try to use the command "Get-ChildIte" (missing the m at the end) directly in PowerShell I get an error message. But with my code, it just doesn't print anything. I need it to print that error message. If anyone knows of a way this could be done, I'd really appreciate it. Thanks!
Ok, you posted your answer 7 seconds ago. I just wanted to confirm, and give a link to reference for you that may help troubleshoot this in the future.
QProcess Class
Yes, you want the readAllStandardError() function of QProcess.
So, about a minute after I posted this I discovered QProcess's signal readyReadStandardError(), which operates identically to readyReadStandardOutput except that it is emitted when whatever the QProcess is running has an error. I connected this to a slot identical to what I have above but instead printing QString(process->readAllStandardError()).toStdString() and it worked.
Ok, so I am executing a program ./led.sh present in my SBC6845, from my host system using a qt-C++ program. This program basically connects my SBC to my host system. It is the equivalent of "hyperterminal" or "Minicom". I obtained this program (the example code) "uartassistant" inside "qextserialport-1.2rc.zip" from http://code.google.com/p/qextserialport/ .
I came across this link: Running shell command in QT c++ in ubuntu , while searching how to execute a shell command from inside the qt program. I tried and succeeded in executing ./led.sh. Thanks to the link.
I declared
void someaction(); // in the dialog.h
then in dialog.cpp I add this
connect(ui->pushButton, SIGNAL(clicked()), SLOT(someaction()));
and this
void Dialog::someaction()
{
QString command = "sh ./led.sh\r\n"; const char* command2;
command2 = command.toLocal8Bit().data();
port->write(command2);
I was able to do the ledflash in my SBC.
But the problem occurs when I try to stop ./led.sh, I am unable to do so in the uartassistant (bugs, need modification, still working).
But for the time being I am trying to make another pushbutton_1 and put something like "Ctrl+Z" inside and ask ./led.sh to stop.
I came across some other links which I am unable to put due to low reputation points.
I have no idea how to use SIGTERM / kill option[from other links] inside qt app and execute on pushbutton click.
Say if I used kill how would I determine the pidof of multiple such pushbutton actions and assign whom to kill.
Also I would like to add that my SBC has ash [Almquist shell]. So it being low memory clone of Bourne shell, I don't know if it would support normal commands for exiting led.sh.
I have no idea how to use SIGTERM / kill option[from other links]
inside qt app and execute on pushbutton click.
As with so much, Qt gives you an intuitive abstraction that allows you to not have to worry about any of this, namely QProcess. In your case you'd want something like this:
QProcess proc;
proc.start("led.sh");
...
//handle Ctrl-Z event
proc.close();
The first answer here has several other techniques for executing more complicated shell commands.
I have found a temporary solution for my problem. I am yet to try the qprocess action.
In dialog.h I added another function:
void someotheraction();
then in dialog.cpp I did this:
connect(ui->pushButton_2,SIGNAL(clicked()), SLOT(someotheraction()));
and this:
void Dialog::someotheraction()
{
QString command = "\x001a \r\n"; const char* command2; // Ctrl-Z = \x001a
command2 = command.toLocal8Bit().data();
port->write(command2);}
The fifth reply here gave me the idea. I don't know how, but it did the job maybe some one can explain it better.
How can I start a Shell Script using QProcess?
The Shell Script has eight different commands in it, some with arguments others without.
I tried to start the Shell Script with (using Ubuntu 11.10):
QProcess *Prozess = new QProcess();
Prozess->setWorkingDirectory(MainDirectory);
Prozess->start("/bin/sh", QStringList() << "Shell.sh");
But this doesn't work, that means nothing happens. How to make it work?
Code is fine. Problem is at run-time.
Either your program can't run /bin/sh for some reason (test if you can run gedit instead?), or the MainDirectory variable has wrong directory path (debug it), or the Shell.sh does not exist in that directory (capitalization mistakes? What about "./Shell.sh"?), or you don't have enough privileges to run or modify target directory/files (are they owned by you?).
The process you have started is running in background. if you want to see any explicit output from the running script you have to connect to void readyReadStandardOutput() or/and void readyReadStandardError() and read from the process explicitly. For example:
void onReadyRead() {
QByteArray processOutput = Prozess->readAllStandardOutput();
}
This should work:
QProcess::ProcessError Error = myProcess->readAllStandardError();
return Error;
QProcess ().execute ("/bin/sh " + MainDirectory + "/Shell.sh");
will do the job.