Обработчик необработанных исключений в .NET 1.1

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

Я добавил обработчики в Application.ThreadException и AppDomain.CurrentDomain.UnhandledException, которые вызываются. Моя проблема в том, что стандартный диалог ошибки CLR все еще отображается (до вызова обработчика исключений).

Джефф рассказывает об этой проблеме в своем блоге здесь и здесь . Но решения нет. Итак, каков стандартный способ обработки неперехваченных исключений в .NET 1.1 и отображения удобного диалогового окна?

Ответ Джеффа был отмечен как правильный, потому что предоставленная им ссылка содержит наиболее полную информацию о том, как сделать то, что требуется.

Ответов (5)

Решение

О, в Windows Forms вы определенно сможете заставить его работать. Единственное, на что вам нужно обратить внимание, это то, что что-то происходит в разных потоках.

У меня есть старая статья Code Project, которая должна помочь:

Удобная для пользователя обработка исключений

Это консольное приложение или приложение Windows Forms? Если это консольное приложение .NET 1.1, то это, к сожалению, задумано - разработчик MSFT подтвердил это во втором сообщении блога, на которое вы ссылались :

Кстати, на моей машине 1.1 пример из MSDN действительно дает ожидаемый результат; просто вторая строка не появляется до тех пор, пока вы не подключите отладчик (или нет). В версии 2 мы изменили ситуацию так, что событие UnhandledException срабатывает до подключения отладчика, что, похоже, является тем, чего ожидает большинство людей.

Похоже, .NET 2.0 делает это лучше (слава богу), но, честно говоря, у меня никогда не было времени вернуться и проверить.

Это приложение Windows Forms. Исключения, которые перехватываются Application.ThreadException, работают нормально, и я не получаю уродливого окна исключений .NET ( OKдля завершения, Cancelдля отладки? Кто это придумал?).

Я получал некоторые исключения, которые не были пойманы этим, и в итоге перешел к событию AppDomain.UnhandledException, которое вызывало проблемы. Думаю, я перехватил большинство этих исключений и теперь показываю их в нашем красивом окне ошибок.

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

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

За кулисами произошло следующее: инфраструктура обнаружила исключение, поднялась по стеку вызовов до самого верха, не нашла обработчиков, которые могли бы восстановиться после ошибки, поэтому не смогла определить, безопасно ли продолжить выполнение. Итак, он запустил последовательность выключения и запустил это событие в знак любезности к вам, чтобы вы могли отдать дань уважения своему и без того обреченному процессу. Это происходит, когда исключение остается необработанным в основном потоке.

Однозначного решения этой ошибки не существует. Вам необходимо поместить реальный обработчик исключений (блок catch) выше всех мест, где возникает эта ошибка, и направить его (например) глобальному методу / классу обработчика, который определит, безопасно ли просто сообщить и продолжить, на основе тип исключения и / или содержание.

Изменить: можно отключить (= взломать) механизм сообщений об ошибках, встроенный в Windows, чтобы обязательное диалоговое окно «сбой и сжигание» не отображалось, когда ваше приложение выходит из строя. Однако это вступает в силу для всех приложений в системе, а не только для вашего собственного.

Поведение необработанного исключения в приложении Windows Forms .NET 1.x зависит от:

  • Тип потока, вызвавшего исключение.
  • Произошло ли это во время обработки оконного сообщения
  • Подключен ли к процессу отладчик
  • Параметр реестра DbgJitDebugLaunchSetting
  • Флаг jitDebugging в App.Config
  • Отменили ли вы обработчик исключений Windows Forms
  • Обработали ли вы событие исключения CLR
  • Фаза луны

Поведение по умолчанию для необработанных исключений:

  • Если исключение возникает в основном потоке при перекачке оконных сообщений, оно перехватывается обработчиком исключений Windows Forms.
  • Если исключение возникает в основном потоке при перекачке оконных сообщений, оно завершит процесс приложения, если оно не будет перехвачено обработчиком исключений Windows Forms.
  • Если исключение возникает в ручном потоке, потоке пула или финализаторе, оно проглатывается CLR.

Контактные лица в случае необработанного исключения:

  • Обработчик исключений Windows Forms.
  • Переключатель реестра JIT-отладки DbgJitDebugLaunchSetting.
  • Событие необработанного исключения CLR.

Встроенная обработка исключений Windows Form по умолчанию выполняет следующие действия:

  • Ловит необработанное исключение, когда:
    • исключение находится в основном потоке, и отладчик не подключен.
    • исключение возникает во время обработки оконного сообщения.
    • jitDebugging = false в App.Config.
  • Показывает диалог пользователю и предотвращает завершение работы приложения.

Вы можете отключить последнее поведение, установив jitDebugging = true в App.Config . Но помните, что это может быть ваш последний шанс остановить завершение работы приложения. Итак, следующим шагом для перехвата необработанного исключения является регистрация для события Application.ThreadException, например:

Application.ThreadException += new
Threading.ThreadExceptionHandler(CatchFormsExceptions);

Обратите внимание на параметр реестра DbgJitDebugLaunchSetting в разделе HKEY_LOCAL_MACHINE \ Software.NetFramework. Это одно из трех значений, о которых я знаю:

  • 0: показывает диалоговое окно пользователя с запросом «отладить или завершить».
  • 1: позволяет CLR обрабатывать исключение.
  • 2: запускает отладчик, указанный в ключе реестра DbgManagedDebugger.

В Visual Studio перейдите в меню ИнструментыПараметрыОтладкаJIT, чтобы установить для этого ключа значение 0 или 2. Но значение 1 обычно лучше всего подходит для конечного пользователя. Обратите внимание, что этот раздел реестра применяется до события необработанного исключения среды CLR.

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

AppDomain.CurrentDomain.UnhandledException += new
System.UnhandledExceptionEventHandler(CatchClrExceptions);