Запустите пользовательский исполняемый файл с QProcess, выйдя сразу с кодом выхода 1 - PullRequest
1 голос
/ 23 октября 2019

Мне нужно запустить собственный исполняемый файл в моем приложении. У меня есть следующий код для запуска моего процесса:

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

Приложение (консольное приложение qt) работает, как и ожидалось, используя

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

, который кратко открывает новое окно CMD с закодированнымвыход, альтернативно открывающий cmd.exe и работающий

C:\Path\To\AwesomeConsoleApp.exe

, отображает вывод на stdout в том же окне cmd.

Сигнал процесса запускается следующим образом:

  1. stateChanged Starting
  2. stateChanged Running
  3. QProcess::started
  4. stateChanged NotRunning
  5. QProcess::finished: выход Exit[1] 0

Я попытался заменить .exe для запуска на C:\Windows\System32\calc.exe, и он запустился без проблем.

Значит ли это, что что-то не так с моим настраиваемым исполняемым файлом?

1 Ответ

1 голос
/ 25 октября 2019

Мысль об удалении вопроса, но если он может быть полезен, я опубликую ответ, который может помочь кому-то в будущем.

Проблема не в коде вызывающего приложения иликод вызываемого приложения (т. е. MaintenanceTool, как показано выше). Вместо этого это была проблема с привилегиями MaintenanceTool.

Итак, мой MaintenanceTool требует административных привилегий для выполнения. Мое приложение для вызова не работает с правами администратора, а мое MaintenanceTool работает. Для этого я использовал QProcess для облегчения запуска приложения MaintenanceTool.

Примечание : Чтобы получить административные привилегии, я использовал this как источник вдохновения для работы шахты.

Я пробовал комбинациииз следующего: QProcess, обратите внимание, что ни один из них не работал для запуска приложения в качестве администратора !

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

Я также создал QProcess *p, добавил readStandardOutput() и т. д. (как показано в вопросе), которые обеспечивают Exit Code 0. Кроме того, я также попытался распечатать все команды приложения и вызывать их вручную в качестве параметров при отладке приложения MaintenaceTool. При запуске с ручными аргументами MaintenanceTool работал (в режиме отладки Qt) и работал должным образом, что меня сильно смутило (но не показало всплывающее окно с диалоговыми окнами привилегий администратора - в то время не заметил)).

Рассматривая фактический код Qt QProcess::startDetached(), я наконец-то наткнулся на сообщение error string своего рода (которое никогда не отправлялось как фактический вывод или errorString), но сохранялось в переменной. По сути, он упомянул, что не смог запустить приложение, требующее прав администратора. Таким образом, я искал и наткнулся на ShellExecuteEx пример, найденный здесь .

Моя реализация из 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.cS =sizeof (SHELLEXECUTEINFO);

ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;

ShExecInfo.hwnd = NULL;

ShExecInfo.lp *erb = L "runas"; 1070 *; 1070; 1070ShExecInfo.lpFile = file;

ShExecInfo.lpParameters = arg;

ShExecInfo.lpDirectory = NULL;

ShExecInfo.nShow = SW_SHOW;

ShExecInfo. hInstApp = NULL;

ShellExecuteEx (& ShExecInfo);

Использование ShellExecuteEx решило мою проблему и позволило приложению работать без проблем, при всплывающем диалоговом окне администратора runasкогда приложение запущено.

Надеюсь, это кому-нибудь поможет!

...