1
votes

I need to run a custom executable in my application. I have the following code to run my process:

QFileInfo fiUpdator(updatorLocation);
if(!fiUpdator.isExecutable()) {
    qWarning() << "Maintenance Tool is not an executable";
    return;
}

qDebug() << "Starting updator app";
QString pid = QString::number(qApp->applicationPid());
QString appName = qApp->applicationName();

QProcess *p = new QProcess;

connect(p, &QProcess::started, this, [this](){
    qDebug() << "Updator Process Started";
});

connect(p, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error){
    qDebug() << "Error Occurred : " << error;
});

connect(p, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this, p](){
    qDebug() << "Finished Updator Process";
    QString str("Exit [" + QString::number(p->exitCode()) + "] " + p->exitStatus());
    qDebug() << str;
});

connect(p, &QProcess::readyReadStandardError, this, [this, p](){
    QByteArray ba = p->readAllStandardError();
    qDebug() << "Error:\n" << QString::fromUtf8(ba);
});

connect(p, &QProcess::readyReadStandardOutput, this, [this, p](){
    QByteArray ba = p->readAllStandardOutput();
    qDebug() << "Output:\n" << QString::fromUtf8(ba);
});

connect(p, &QProcess::stateChanged, this, [this](QProcess::ProcessState newState){
    qDebug() << "State Changed : " << newState;
});

p->start(
            updatorLocation,
            QStringList()
                << pid
                << appName
                << newFilePath
                << oldFilePath);

The application (a qt console application) runs as expected using

start "" "C:\Path\To\AwesomeConsoleApp.exe" 

which briefly opens a new CMD window with the coded output, alternatively opening cmd.exe and running

C:\Path\To\AwesomeConsoleApp.exe

displays the output to stdout in the same cmd window.

The process signal fire as follows:

  1. stateChanged Starting
  2. stateChanged Running
  3. QProcess::started
  4. stateChanged NotRunning
  5. QProcess::finished : output Exit[1] 0

I tried replacing the .exe to launch with C:\Windows\System32\calc.exe and it launched with no problem.

Does this mean there is something wrong with my custom executable?

1
QProcess::ExitStatus 0 means that The process exited normally. May be executable is reacting to arguments with exit code 1. Try to print all arguments and run executable with them manually. - uni
@uni got it resolved, see posted answer. - CybeX

1 Answers

1
votes

Thought of deleting the question but incase it could be of use, I will post an answer which may help someone in future.

The problem was not in the calling application code or the called application's code (i.e. the MaintenanceTool as shown above). Instead, it was a problem with the MaintenanceTool privileges.

So, my MaintenanceTool requires administrative privileges to execute. My calling application does not run with Administrative proviledges, but my MaintenanceTool does. For this, I was using QProcess to facilitate launching the MaintenanceTool application.

Note: To gain administrative priviledges, I used this as inspiration to get mine working.

I tried combinations of the following with QProcess, note that none of these worked for running an app as admin!

QProcess::startDeteched("cmd.exe", QStringList() << "/C" << "/path/to/mtool.exe -arg1 -arg2");

QProcess::startDeteched("cmd.exe", QStringList() << "/C" << "/path/to/mtool.exe -arg1 -arg2");

QProcess::startDeteched("start.exe", QStringList() << "" << "/path/to/mtool.exe -arg1 -arg2");

QProcess::startDeteched("C:\Windows\System32\cmd.exe", QStringList() << "/C" << "/path/to/mtool.exe -arg1 -arg2");

QProcess::startDeteched("C:\Windows\System32\cmd.exe", QStringList() << "/C" << "/path/to/mtool.exe -arg1 -arg2");

QProcess::startDeteched("/path/to/mtool.exe", QStringList() << "" << "-arg1" << "-arg2");

I also created a QProcess *p, added readStandardOutput(), etc (as shown in question) which provide Exit Code 0. Further, I also tried printing out all the commands to the application, and invoking them manually as params when debugging the MaintenaceTool application. Running it with manual arguments had the MaintenanceTool running (using Qt debug mode) and working as expected which had me quite confused (but did not show the admin privileges dialog popup - didn't notice at the time).

Looking into the QProcess::startDetached() actual Qt code, I finally came across a message error string of sorts (which was never sent as an actual output or errorString) but was stored in a variable. Essentially, it mentioned that it was unable to start an application that required Administrator privileges. Thus, I searched and came across the ShellExecuteEx example found here.

My Implementation of ShellExecuteEx

QString args = QString("\"%1\" \"%2\" \"%3\" \"%4\" \"%5\"").arg(pid).arg(appName).arg(logLocation).arg(newFilePath).arg(oldFilePath);

LPCWSTR file = reinterpret_cast(updatorLocation.utf16());

LPCWSTR arg = reinterpret_cast(args.utf16());

SHELLEXECUTEINFO ShExecInfo = {0};

ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);

ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;

ShExecInfo.hwnd = NULL;

ShExecInfo.lpVerb = L"runas";

ShExecInfo.lpFile = file;

ShExecInfo.lpParameters = arg;

ShExecInfo.lpDirectory = NULL;

ShExecInfo.nShow = SW_SHOW;

ShExecInfo.hInstApp = NULL;

ShellExecuteEx(&ShExecInfo);

Using the ShellExecuteEx solved my problem and allowed the application to run without a problem, with runas admin dialog popping up when the application is launched.

I hope this helps someone!