How to start a Shell Script with QProcess? - c++

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.

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.

QProcess working example - C++

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");

How can I find why system can not run my application?

I have a c++ program that run a command and pass some arguments to it. The code is as follow:
int RunApplication(fs::path applicationPathName,std::string arguments)
{
std::string applicationShortPath=GetShortFileName(applicationPathName);
std::string cmd="\""+applicationShortPath +"\" "+ arguments+" >>log.txt 2>&1 \"";
std::cout<<cmd<<std::endl;
int result=std::system(cmd.c_str());
return result;
}
When I run system command, the cmd window appears shortly and then closes, but the result is 1 and the cmd was not run (the command should generate output which is not generated).
To check that the cmd is correct, I stopped the application just before system line and copy/ paste cmd content to a cmd window and it worked.
I am wondering how can I find why application is not run in system()?
the cmd has this value just before running it:
"D:/DEVELO~3/x64/Debug/enfuse.exe" -w --hard-mask --exposure-weight=1 --saturation-weight=0.328 --contrast-weight=0.164 -o "C:/Users/m/AppData/Local/Temp/1.tif" "C:/Users/m/AppData/Local/Temp/1.jpg" "C:/Users/m/AppData/Local/Temp/2.jpg" >>log.txt 2>&1 "
How can I find why it is not working?
Is there any way that I set the system so it doesn't close cmd window so I can inspect it?
is there any better way to run a command on OS?
Does Boost has any solution for this?
Edit
After running it with cmd /k, I get this error message:
The input line is too long.
How can I fix it other than reducing cmd line?
There are two different things here: if you have to start a suprocess, "system" is not the best way of doing it (better to use the proper API, like CreateProcess, or a multiplatform wrapper, but avoid to go through the command interpreter, to avoid to open to potential malware injection).
But in this case system() is probably the right way to go since you in fact need the command interpreter (you cannot manage things like >>log.txt 2>&1 with only a process creation.)
The problem looks like a failure in the called program: may be the path is not correct or some of the files it has to work with are not existent or accessible with appropriate-permission and so on.
One of the firt thing to do: open a command prompt and paste the string you posted, in there. Does it run? Does it say something about any error?
Another thing to check is how escape sequence are used in C++ literals: to get a '\', you need '\\' since the first is the escape for the second (like \n, or \t etc.). Although it seems not the case, here, it is one of the most common mistakes.
Use cmd /k to keep the terminal: http://ss64.com/nt/cmd.html
Or just spawn cmd.exe instead and inspect the environment, permissions, etc. You can manually paste that command to see whether it would work from that shell. If it does, you know that paths, permssions and environment are ok, so you have some other issue on your hands (argument escaping, character encoding issues)
Check here How to execute a command and get output of command within C++ using POSIX?
Boost.Process is not official yet http://www.highscore.de/boost/process/

How to stop a process running in a shell in a different system?

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.

Problems passing source command to bash from c++ application

I am developing an application for work that allows the users to quickly set environment variables on a terminal basis. By setting the path in each terminal we ensure files with the same name in different directories aren't causing application testing to be problematic. I am Using Qt to build the program which is c++ based and all the datatypes are foundationally the same.
I am using the following code to invoke commands in the terminal from which the application launches from using system(). I can run commands into the bash just fine with code; however, I run into a problem when I attempt to use a command with arguments. This is probably why source doesn't seem to work right as the source command is followed by the filename. It would appear that I drop the argument appended after the bash command.
My Code:
void assignTerminalToPath(QString path)
{
QString data = "";
QString currentUsersHomeDirectory = QDir::homePath();
QString tmpScriptLocation = currentUsersHomeDirectory;
QByteArray ba;
tmpScriptLocation += "/.tmpSourceFile";
QFile tmpSourceFile(tmpScriptLocation);
if(tmpSourceFile.open(QFile::WriteOnly | QFile::Truncate))
{
QTextStream output(&tmpSourceFile);
data.append("export PATH=.:");
data.append(path);
data.append(":$PATH");
output << QString("#!/bin/bash\n");
output << data;
tmpSourceFile.close();
}
data.clear();
data.append("/bin/bash -c source ");
data.append(tmpScriptLocation);
ba = data.toLatin1();
const char *cStr = ba.data();
system(cStr);
}
Perhaps I'm not referencing bash correctly and I need something outside of -c?
Reference Execute shell/bash command using C/C++
Thanks for any help in advance!
source is not a program that you can call, it is embedded bash command. It is designed to be processed by bash without invoking another copy of bash, such that environment variables can be changed in current bash copy.
However, you cannot call source as part of system(). And even if you did succeed at that, its effects to change environment variables would be completely lost for caller app once system() has returned.
Try a command to envelop with parameters in double quotes ("command - arg1 - to arg2") to transfer in the function system().
used:
char *com = "\"command -arg1 -arg2\"";
system(com);