How to use QProcess? - qt

I want to open a project of QGIS from a QProcess object.
If I am under console I must type
qgis --project /path/of/my/qgis/project/nameofproject.qgs
Then, I do the next:
QString app="qgis";
QStringList arguments;
arguments.append ("--project /path/of/my/qgis/project/nameofproject.qgs");
And then I call it in this way:
proceso->start(app,arguments);
But I have this error in the call:
Cannot find /home/david/Programacion/Qt/SQL/Sql2/build-prueba2-Desktop_Qt_5_3_GCC_64bit-Debug/--project /home/david/GIS/CRCC.qgs
where:
/home/david/Programacion/Qt/SQL/Sql2/build-prueba2-Desktop_Qt_5_3_GCC_64bit-Debug/ is the path of my Qt application and
--project /home/david/GIS/CRCC.qgs is the path I set in the arguments QStringList
I don know how must I set the QProcess object for avoid the path of my app.
Thank you

I would try this in the following ways. With a single command:
const QString command( "qgis --project /path/of/my/qgis/project/nameofproject.qgs" );
QProcess process;
process.start( command );
Or with arguments:
const QString program( "qgis" );
QStringList arguments;
arguments << "--project";
arguments << "/path/of/my/qgis/project/nameofproject.qgs";
QProcess process;
process.start( program, arguments );

Related

arp command with grep argument in QProcess [duplicate]

I'm using Qt and bash over it, need to execute something like:
bash: cat file | grep string
in Qt:
QString cmd = "cat file | grep string";
QProcess *process = new QProcess;
process->start(cmd);
process->waitForBytesWritten();
process->waitForFinished();
qDebug() << process->readAll();
The problem is in pipe ("|"), and process returs nothing. If there is no ("|"), like
"cat file"
everything is ok.
I tried smth. like
"cat file \\| grep string",
"cat file \| grep string"
but result is the same. If I copy the command and run it in bash everything is ok.
QString::toAscii().data()
and other transforms also have bad result.
The problem is you cannot run a system command with QProcess, but only a single process. So the workaround will be to pass your command as an argument to bash:
process.start("bash", QStringList() << "-c" << "cat file | grep string");
The quick and dirty hack would be this:
QString cmd = "/bin/sh -c \"cat file | grep string\"";
You could also avoid the escaping in there with C++11's R"", but the point is that do not use bash in there because that will make it only work with bash. It will not work on embedded with busybox without bash, just ash, or any other common desktop shell.
/bin/sh is usually a symlink to the shell interpreter used, so that will eventually work.
BUT!
I think you are thinking a bit too low-level when using a high-level C++/OOP framework such as Qt. I would not recommend to invoke the commands in the low-level way when you run it from bash. There is some dedicated high-level convenience API for this use case.
Based on the official documentation, QProcess is supposed to work for pipe'd commands:
void QProcess::setStandardOutputProcess(QProcess * destination)
Pipes the standard output stream of this process to the destination process' standard input.
In other words, the command1 | command2 shell command command can be achieved in the following way:
QProcess process1;
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("cat file");
process2.start("grep string");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
// Wait for it to start
if(!process1.waitForStarted())
return 0;
bool retval = false;
QByteArray buffer;
while ((retval = process2.waitForFinished()));
buffer.append(process2.readAll());
if (!retval) {
qDebug() << "Process 2 error:" << process2.errorString();
return 1;
}
qDebug() << "Buffer data" << buffer;
This is not the main point, but a useful suggestion: do not use QString::toAscii(). That API has been deprecated in Qt 5.
The problem is that when you call process->start(cmd), the commands following the the call to cat are all interpreted as arguments to cat, so the pipe is not doing what you're expecting. If you start with a call to bash with a parameter of a string, you should get what you want: -
QString cmd = "bash -c \"cat file | grep string\"";
Alternatively, you could just call "cat file" and do the search on the returned QString when you read the output from the QProcess
how about this :
QString program = "program";
QStringList arguments;
download = new QProcess(this);
download->start(program, arguments);
If Google brought you here and you are using PyQt5 or PySide2
process1 = QProcess()
process2 = QProcess()
process1.setStandardOutputProcess(process2)
process1.start(cat, [file])
process2.start(grep, [string])

Can I use QCommandLineParser to determine GUI mode or CLI mode?

One of the programs that I work with has two modes that it can run in: GUI (Graphical User Interface) mode or CLI (Command-Line Interface) mode. We determine which mode to use via a command line argument (i.e., if "--cli" is passed, it will use CLI mode).
The type of QApplication that is instantiated depends on which mode is used: QApplication should be used for GUI mode, and QCoreApplication should be used for CLI mode, because the GUI parts of Qt should not be instantiated for CLI mode (since CLI mode does not use or need them).
I can do that via code similar to the following:
std::unique_ptr<QCoreApplication> app =
(cliMode) ? std::make_unique<QCoreApplication>(argc, argv)
: std::make_unique<QApplication>(argc, argv);
// Do some other stuff...
return app->exec();
Since I am already using Qt, it makes sense to use QCommandLineParser to parse my arguments. After parsing the arguments, I want to analyze them to determine whether we should run in GUI mode or CLI mode. However, it has been becoming increasingly difficult to do so.
The first problem I noticed was the following on Linux (this did not happen in older versions of Qt5, but it does happen in the newer versions):
$ ./myQtApplication --help
QCoreApplication::arguments: Please instantiate the QApplication object first
Segmentation fault (core dumped)
Okay: so I can no longer run the --help command without already having a QApplication object instantiated. I temporarily fixed this by manually parsing the arguments to see whether or not --help is an argument. If it is, go ahead and instantiated the QCoreApplication, parse the arguments, and then exit.
But then I started getting a cryptic error on Mac OS X. When I would run the executable on OS X directly, it would run without any issues. But if I tried to double-click on the .app file or type in the terminal $ open myQtApplication.app, I would get this cryptic error:
LSOpenURLsWithRole() failed with error -10810 for the file ./myQtApplication.app
Since it is a rather cryptic error, it took me a long time to figure out that this error was being caused by the QCommandLineParser being used before having a QApplication object instantiated.
To fix this, I am now doing the following:
Manually parse the arguments at the beginning of the main() function to determine whether or not --cli was passed.
Instantiate a QApplication object based on the results of #1.
Run QCommandLineParser to process the rest of the arguments.
This is not a very clean way to do this because I now have two argument parsers: one to determine if --cli was passed, and the rest for the other arguments.
Is there a much better, or "proper", way to do this?
I guess the main question is: can I use QCommandLineParser to determine whether to instantiate a QCoreApplication object or a QApplication object?
Of course you can use the parser - as long as QCoreApplication already present. If the --cli option is absent, you will switch to a QApplication. Recall that you have full control over the lifetime of the application object.
This works under Qt 4.8 and 5.11 on both Windows and OS X:
// https://github.com/KubaO/stackoverflown/tree/master/questions/app-cli-gui-switch-52649458
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets>
#endif
struct Options {
bool cli;
};
static Options parseOptionsQt4() {
Options opts = {};
for (auto arg : QCoreApplication::arguments().mid(1)) {
if (arg == "--cli")
opts.cli = true;
else
qFatal("Unknown option %s", arg.toLocal8Bit().constData());
}
return opts;
}
static Options parseOptions() {
if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) return parseOptionsQt4();
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Options opts = {};
QCommandLineParser parser;
QCommandLineOption cliOption("cli", "Start in command line mode.");
parser.addOption(cliOption);
parser.process(*qApp);
opts.cli = parser.isSet(cliOption);
return opts;
#endif
}
int main(int argc, char *argv[]) {
QScopedPointer<QCoreApplication> app(new QCoreApplication(argc, argv));
auto options = parseOptions();
if (options.cli) {
qDebug() << "cli";
} else {
qDebug() << "gui";
app.reset();
app.reset(new QApplication(argc, argv));
}
if (qobject_cast<QApplication *>(qApp))
QMessageBox::information(nullptr, "Hello", "Hello, World!");
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
return app->exec();
}

SCP always returns the same error code

I have a problem copying files with scp. I use Qt and copy my files with scp using QProcess. And when something bad happens I always get exitCode=1. It always returns 1. I tried copying files with a terminal. The first time I got the error "Permission denied" and the exit code was 1. Then I unplugged my Ethernet cable and got the error "Network is unreachable". And the return code was still 1. It confuses me very much cause in my application I have to distinct these types of errors.
Any help is appreciated. Thank you so much!
See this code as a working example:
bool Utility::untarScript(QString filename, QString& statusMessages)
{
// Untar tar-bzip2 file, only extract script to temp-folder
QProcess tar;
QStringList arguments;
arguments << "-xvjf";
arguments << filename;
arguments << "-C";
arguments << QDir::tempPath();
arguments << "--strip-components=1";
arguments << "--wildcards";
arguments << "*/folder.*";
// tar -xjf $file -C $tmpDir --strip-components=1 --wildcards
tar.start("tar", arguments);
// Wait for tar to finish
if (tar.waitForFinished(10000) == true)
{
if (tar.exitCode() == 0)
{
statusMessages.append(tar.readAllStandardError());
return true;
}
}
statusMessages.append(tar.readAllStandardError());
statusMessages.append(tar.readAllStandardOutput());
statusMessages.append(QString("Exitcode = %1\n").arg(tar.exitCode()));
return false;
}
It gathers all available process output for you to analyse. Especially look at readAllStandardError().

Error in processing command in QProcess

I am trying to execute following command and trying to get the output however I am getting output as null.
QProcess process;
process.start("cmd /c \"ipconfig\"");
process.waitForFinished(-1);
QByteArray out = process.readAll();
QString testStr = QString::fromUtf8(out);
Can someone please tell me where am I doing wrong?
process.start("C:\\Windows\\System32\\cmd.exe /c \"ipconfig\"");

Qt - Wait for Qprocess to finish

I'm using CMD by QProcess but I have a problem.
My code:
QProcess process;
process.start("cmd.exe");
process.write ("del f:\\b.txt\n\r");
process.waitForFinished();
process.close();
When I don't pass an argument for waitForFinished() it waits for 30 secs. I want to terminate QProcess after CMD command is executed! Not much and not less!
You need to terminate the cmd.exe by sending exit command, otherwise it will wait for commands
Here is my suggestion:
QProcess process;
process.start("cmd.exe");
process.write ("del f:\\b.txt\n\r");
process.write ("exit\n\r");
process.waitForFinished();
process.close();
The process you're starting is cmd.exe which, by itself will, not terminate. If you call cmd with arguments, you should achieve what you want: -
QProcess process;
process.start("cmd.exe \"del f:\\b.txt"\"");
process.waitForFinished();
process.close();
Note that the arguments are escaped in quotes.
Alternatively, you could call the del process, without cmd: -
QProcess process;
process.start("del \"f:\\b.txt"\"");
process.waitForFinished();
process.close();
Finally, if you just want to delete a file, you could use the QFile::remove function.
QFile file("f:\\b.txt");
if(file.remove())
qDebug() << "File removed successfully";

Resources