Можно ли предотвратить создание отчетов об ошибках Microsoft для одного приложения? - PullRequest
6 голосов
/ 05 августа 2010

У нас есть неуправляемое приложение C ++, которое использует сторонние API для чтения файлов САПР. На некоторых поврежденных файлах САПР происходит сбой сторонней библиотеки, которая отключает наш EXE-файл. Из-за этого наше основное приложение представляет собой отдельный EXE-файл, и таким образом он не подвержен сбою. Как бы то ни было, мы получаем раздражающие диалоги отчетов об ошибках Microsoft.

Я не хочу отключать всю систему отчетов об ошибках Microsoft. Есть ли способ отключить создание отчетов об ошибках для одного приложения, чтобы в случае его сбоя происходило тихое завершение без всплывающих диалогов об ошибках?

Ответы [ 5 ]

5 голосов
/ 05 августа 2010

Ответ Ханса Пассанта о SetUnhandledExceptionFilter находится на правильном пути.Он также делает несколько хороших замечаний о невозможности сделать слишком много в обратном вызове, потому что различные части процесса могут находиться в нестабильном состоянии.

Однако, из описания способа, это неПохоже, вы хотите сделать что-нибудь, кроме как сказать системе не выводить нормальный диалог сбоя.В этом случае это легко и должно быть безопасно независимо от того, на какие части процесса мог повлиять сбой.

Создайте функцию примерно так:

LONG WINAPI UnhandledExceptionCallback(PEXCEPTION_POINTERS pExceptPtrs)
{
    if (IsDebuggerPresent())
        // Allow normal crash handling, which means the debugger will take over.
        return EXCEPTION_CONTINUE_SEARCH;
    else
        // Say we've handled it, so that the standard crash dialog is inhibited.
        return EXCEPTION_EXECUTE_HANDLER;
}

И где-нибудь в вашей программе(вероятно, как можно раньше) установите обратный вызов:

SetUnhandledExceptionFilter(UnhandledExceptionCallback);

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

Однако есть еще кое-что дляОбратите внимание на это: каждый раз, когда вы добавляете сторонние компоненты (DLL, OCX и т. д.), существует риск того, что один из них может также вызвать SetUnhandledExceptionFilter и, таким образом, заменить ваш обратный вызов своим собственным.Однажды я столкнулся с элементом управления ActiveX, который устанавливал свой собственный обратный вызов при создании экземпляра.И что еще хуже, он не смог восстановить первоначальный обратный вызов, когда он был уничтожен.Это казалось ошибкой в ​​их коде, но, несмотря на это, мне пришлось предпринять дополнительные шаги, чтобы гарантировать, что мой желаемый обратный вызов был восстановлен, по крайней мере, тогда, когда это должно было произойти после того, как их управление было отключено.Поэтому, если вы обнаружите, что это иногда не работает для вас, даже если вы знаете, что правильно установили обратный вызов, вы можете столкнуться с чем-то похожим.

5 голосов
/ 05 августа 2010

В Vista и выше функция API WerAddExcludedApplication может использоваться для исключения указанного исполняемого файла приложения из отчетов об ошибках.Насколько мне известно, аналогичной опции в XP и других устаревших версиях ОС нет.

Однако, поскольку WER включит только необработанные исключения приложений, вы сможете отменить его, добавив "универсальный обработчик исключений для вашего EXE.Посмотрите векторную обработку исключений для некоторых идей о том, как этого добиться.

Обратите внимание, что подавление всех необработанных исключений, как правило, является плохой идеей (и, например, приведет к тому, что ваше приложение не пройдет сертификацию Windows Logo), поэтому не следует использовать эту технику без разбора ...

5 голосов
/ 05 августа 2010

Да, есть кое-что, что вы можете сделать. Вызовите SetUnhandledExceptionFilter () в вашем методе main () для регистрации обратного вызова. Он вызывается, когда никто не желает обработать исключение, перед тем, как появится диалоговое окно Microsoft WER.

На самом деле выполнение чего-либо в этом обратном вызове чревато проблемами. Программа умерла с неизменно чем-то неприятным, как исключение AccessViolation. Который часто споткнулся из-за коррупции в куче. Попытка сделать что-то вроде отображения окна сообщения, чтобы сообщить пользователю, проблематична, когда куча тостов. Deadlock всегда скрывается за углом, готовый просто заблокировать программу без какой-либо диагностики.

Единственное, что можно сделать безопасно - это иметь вспомогательный процесс, который защищает ваш основной процесс. Разбудите его, сигнализируя именованное событие в вашем обратном вызове. Дайте ему информацию об исключении, которая ему нужна, с отображенным в память файлом. Помощник может делать практически все, что хочет, когда видит событие. В том числе показ сообщения, взятие минидампа. И прекращение основного процесса.

Именно так работает помощник Microsoft WerFault.

2 голосов
/ 21 сентября 2010

Я оказался именно в такой ситуации при разработке приложения для Delphi.Я обнаружил, что мне нужно две вещи, чтобы надежно подавить диалоговое окно «приложение перестало работать».

Вызов SetErrorMode(SEM_NOGPFAULTERRORBOX); подавляет диалоговое окно «приложение перестало работать».Но затем обработчик исключений Delphi отображает окно сообщения с сообщением об ошибке времени выполнения.

Чтобы подавить обработчик исключений Delphi, я вызываю SetUnhandledExceptionFilter с пользовательским обработчиком, который завершает процесс, вызывая Halt.

Таким образом, скелет для клиентского приложения Delphi, выполняющего код, склонный к сбоям, становится:

function HaltOnException(const ExceptionInfo: TExceptionPointers): Longint; stdcall;
begin
  Halt;
  Result := 1;  // Suppress compiler warning
end;

begin
  SetErrorMode(SEM_NOGPFAULTERRORBOX);
  SetUnhandledExceptionFilter(@HaltOnException);
  try
    DoSomethingThatMightCrash;
  except
    on E: Exception do
      TellServerWeFailed(E.Message);
  end;
end.
0 голосов
/ 05 августа 2010

Я не совсем уверен, но, возможно, SetErrorMode или SetThreadErrorMode будет работать для вас?

...