Command Working in Terminal, But Not via Qprocess

Command working in terminal, but not via QProcess

QProcess executes one single process. What you are trying to do is executing a shell command, not a process. The piping of commands is a feature of your shell.

There are three possible solutions:

Put the command you want to be executed as an argument to sh after -c ("command"):

QProcess sh;
sh.start("sh", QStringList() << "-c" << "ifconfig | grep inet");

sh.waitForFinished();
QByteArray output = sh.readAll();
sh.close();

Or you could write the commands as the standard input to sh:

QProcess sh;
sh.start("sh");

sh.write("ifconfig | grep inet");
sh.closeWriteChannel();

sh.waitForFinished();
QByteArray output = sh.readAll();
sh.close();

Another approach which avoids sh, is to launch two QProcesses and do the piping in your code:

QProcess ifconfig;
QProcess grep;

ifconfig.setStandardOutputProcess(&grep); // "simulates" ifconfig | grep

ifconfig.start("ifconfig");
grep.start("grep", QStringList() << "inet"); // pass arguments using QStringList

grep.waitForFinished(); // grep finishes after ifconfig does
QByteArray output = grep.readAll(); // now the output is found in the 2nd process
ifconfig.close();
grep.close();

Command run in terminal but not in QProcess while PATHs are inserted

After a-lot of searches, finally I found-out that there was a problem with LD_LIBRARY_PATH which does not considered by Qt.

Without any using of setProcessEnvironment(...), I open terminal and export the LD_LIBRARY_PATH just before running it as follows:

export LD_LIBRARY_PATH 
exec "./my_app"

Then my_app is aware of all libraries stored LD_LIBRARY_PATH

QProcess fails to execute a terminal line command via QPushButton

Try this:

header:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QProcess>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:
void on_executeScriptBtn_clicked();

private:
Ui::MainWindow *ui;
QProcess * executeBash;
};
#endif // MAINWINDOW_H

source:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->executeBash = new QProcess(this);
this->executeBash->setProcessChannelMode(QProcess::MergedChannels);
connect(this->executeBash, &QProcess::readyReadStandardOutput, [script = this->executeBash](){
qDebug() << "[EXEC] DATA: " << script->readAll();
});
connect(this->executeBash, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[script = this->executeBash](int exitCode, QProcess::ExitStatus exitStatus){
qDebug() << "[EXEC] FINISHED: " << exitCode << exitStatus;
if(script->bytesAvailable() > 0)qDebug() << "[EXEC] buffered DATA:" << script->readAll();
});
connect(this->executeBash, &QProcess::errorOccurred, [script = this->executeBash](QProcess::ProcessError error){
qDebug() << "[EXEC] error on execution: " << error << script->errorString();
});

}
void MainWindow::on_executeScriptBtn_clicked()
{
qDebug() << "Button clicked!"; // if you don't see this message check your SIGNAL/SLOT connections!
//this->executeBash->execute(...) // <- will wait till script is finished and block main thread
this->executeBash->start(QStringLiteral("/bin/sh"), QStringList() << QStringLiteral("/home/emanuele/Desktop/bags/test.sh")); //will start new process without blocking
}

MainWindow::~MainWindow(){delete ui;}

Qprocess messes my linux command up (i think). how to fix?

QProcess does not support shell commands. The pipe symbols is thus not interpreted by a shell, but instead directly passed to ls. ls interprets it as file name, and complains because apparantly there is no file named |.

You need to setup pipes manually by redirecting input and output streams of QProcess objects. Read the documentation to learn how to do this.

Generally how should avoid shell commands, and instead rely on Qt classes and functions. There is certainly no need to call grep or ls, because the same can be done easier with QRegExp, and QDir. If you need to execute subprocesses, then use the ::start(const QString&, const QStringList&, OpenMode) overload and pass all arguments as list to avoid quoting issues.

QProcess doesn't show the command window

So as discussed in the comments on my questions this StackOverflow post explains that this is infact correct behaviour when using the startDetached() function.

I'm not entirely sure what the answer to that question was suggesting to do but here is my working solution.

system() is a windows specific function which "can execute any command that can run on terminal if operating system allows" link

If I replace this line:

 bool res = QProcess::startDetached(program, arguments);

with the following, then it works:

system(QString("D:\\Qt\\5.9.1\\msvc2017_64\\bin\\myApp.exe " +tableName +" " + fileName).toStdString().c_str());

In the short term I have simply moved this application into the Qt folder because it needs the DLLs however with a proper release of this app you can run it from wherever, including from next to the application that is running it.

I do then get a terminal window and my app runns correctly.

Qt: QProcess to call terminal + script

This snippet may be useful (untested). Refer to QProcess documentation for detail on each method.

process->setWorkingDirectory("/Users/Tim/etcetc");
process->setArguments(QStringList() << "scatterplotscriptwithout.txt");
process->start("/opt/local/bin/gnuplot");

EDIT

Another thing that seem wrong in your program is the undefined pointer that you give as parent to your QProcess instance. It is useful to set a parent to take benefit of an automatic children deletion. In this case, just take care to delete the QProcess instance yourself.

EDIT 2 (error handling)

QProcess *process = new QProcess;
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(handleError(QProcess::ProcessError)));

Then define a proper slot (here handleError)

void MyClass::handleError(QProcess::ProcessError error) {
switch(error) {
case QProcess::FailedToStart:
qDebug() << "Failed to start, may be due to insufficient permissions";
break;
case QProcess::Crashed:
qDebug() << "Program crashed.";
break;
//debug each case..
}
}

See here for a detail of all the enum values.

If your QProcess ends correctly but not with the expected output, you can look at the exit code of your process and refer to the gnuplot man page for information.



Related Topics



Leave a reply



Submit