QProcess :: Crashed. Как избежать сообщения о сбое Windows 10 внешней программы

Предположим, что мы хотим запустить внешнее приложение командной строки, например «dir», и предположим, что оно дает сбой:

namespace util
{

        bool execChildProcess(const std::string & cmd,  std::string & cmdOutput)
        {
           QProcess process;
           QString qStrCmd = QString::fromStdString(cmd);
           process.start(qStrCmd);

           if(process.exitStatus() == QProcess::Crashed )
           {
               std::cout<<"QProcess::Crashed"<<std::endl;
               process.kill();
           }

           if(process.waitForFinished() && process.exitStatus() == QProcess::NormalExit )
           {
               QString output(process.readAllStandardOutput());
               cmdOutput = output.toStdString();
               std::cout<<"Result: "<<cmdOutput<<std::endl;
               return true;
           }
           else
           {
                   switch(process.error())
                   {
                    case QProcess::FailedToStart :
                        std::cout<<"QProcess::FailedToStart"<<std::endl;
                        break ;
                    case QProcess::Crashed :
                        std::cout<<"QProcess::Crashed"<<std::endl;
                        break ;
                    case QProcess::Timedout:
                        std::cout<<"QProcess::Timedout"<<std::endl;
                        break ;
                    case QProcess::WriteError:
                        std::cout<<"QProcess::WriteError"<<std::endl;
                        break ;
                    case QProcess::ReadError:
                        std::cout<<"QProcess::ReadError"<<std::endl;
                        break ;
                    case QProcess::UnknownError:
                        std::cout<<"QProcess::UnknownError"<<std::endl;
                        break ;
                    }
                    process.kill();
           }
           return false;
        }
}

int main(int argc, char* argv[])
{
        std::string output;
        bool res = util::execChildProcess("dir", output);
}

сбой фиксируется после того, как мы закрываем это сообщение:

введите описание изображения здесь

После закрытия сообщения код завершает процесс, но не раньше.

Как мы можем избежать этого сообщения с помощью QProcess (я не знаю, происходит ли это также в ubuntu, но я хотел бы кроссплатформенное решение, если это также произойдет в ubuntu).


person sergio campo    schedule 12.05.2018    source источник


Ответы (3)


Позвоните SetErrorMode(SEM_NOGPFAULTERRORBOX) в свой процесс; режим ошибки наследуется дочерними процессами. Вы можете вернуть его сразу после запуска процесса:

QProcess process;
...
auto errMode = GetErrorMode();
SetErrorMode(errMode | SEM_NOGPFAULTERRORBOX);
connect(&process, &QProcess::stateChanged, [errMode](QProcess::ProcessState state) { if (state != QProcess::Starting) SetErrorMode(errMode); });
process.start();
...

Вы также можете выполнить SetErrorMode(SEM_NOGPFAULTERRORBOX) в целевом процессе. Для этого вы можете создать .DLL, который включает этот вызов, и вставить его в целевой процесс.

Дескриптор целевого процесса можно получить следующим образом:

HANDLE getHandle(const QProcess *process) {
  auto pid = process->processId();
  return pid->hProcess;
}
person Kuba hasn't forgotten Monica    schedule 14.05.2018
comment
Во всех решениях здесь использовался вариант подхода к реестру, включая тот, в котором упоминалось SetErrorMode решение, Считаете ли вы подход к реестру агрессивным? - person Mohammad Kanan; 14.05.2018

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

В разделе реестра Windows отредактируйте:

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ AeDebug

Добавьте значение REG_DWORD в подраздел AutoExclusionList, где имя - это имя исполняемого файла, а значение равно 1.

Вам не нужно делать это вручную в своем приложении, вы можете использовать Qt QSettings следующим образом:

QSettings settings("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug",
QSettings::NativeFormat);
auto key = settings.childKeys().at(x);

Затем вы можете использовать QSettings::setValue, чтобы установить ключ в 1.

Полная информация и ссылки на страницах MSDN Настройка автоматической отладки

Для Ubuntu это нужно контролировать, учитывая, что процесс убит.

person Mohammad Kanan    schedule 12.05.2018
comment
Я редактировал с помощью командной строки regedit. Мне нужно перезапускать окна? Я закрываю только терминал. Внешняя программа представляет собой переносимый двоичный файл .exe, и она не была установлена ​​в системе с помощью мастера Windows. Это не работает. - person sergio campo; 12.05.2018
comment
Полагаю, перезапускать не нужно, но я не уверен, что он не установлен с помощью мастера. - person Mohammad Kanan; 12.05.2018

Как указал Мохаммад Канан, мы можем отключить диалоговое окно ошибки в разделе редактирования реестра, но в этом случае для Windows 10 pro находится под:

HKEY_LOCAL_MACHINE \ Software \ Microsoft \ Windows \ Отчет об ошибках Windows

Найдите значение с именем

DontShowUI

или добавьте новое значение DWORD с этим именем, если оно не существует. Значение по умолчанию для этого ключа - 0. Дважды щелкните его, чтобы отредактировать, измените значение на 1 и сохраните.

person sergio campo    schedule 12.05.2018