Как отключить обработку исключений .NET Framework и использовать вместо этого мой собственный? - PullRequest
11 голосов
/ 17 сентября 2010

Я разработал программное обеспечение .NET 4 и готов отправить его бета-пользователям. Если в программное обеспечение выдается необработанное исключение, я бы хотел его перехватить, записать в журнал и отправить мне. Я уже реализовал эту функцию, и она, кажется, работает нормально, когда я запускаю ее в режиме отладки с Visual Studio. Однако, когда я собрал выпускную версию программного обеспечения и установил его, Microsoft .NET Framework начинает перехватывать исключения перед моим кодом. Я получаю всплывающее окно с сообщением об ошибке: «Необработанное исключение произошло в компоненте вашего приложения. Если вы нажмете« Продолжить », приложение проигнорирует эту ошибку и попытается продолжить.»

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

Я прикрепил свой собственный обработчик исключений с этим кодом:

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

Есть ли способ отключить перехват исключений в .NET Framework или есть лучший способ присоединить мой собственный обработчик исключений?

ОБНОВЛЕНИЕ: Я использую WPF. Я посмотрю на DispatcherUnhandledException и сообщу, решит ли он проблему.

ОБНОВЛЕНИЕ № 2: К сожалению, добавление обработчика в Application.Current.DispatcherUnhandledException не решило проблему. По-видимому, это всплывающее окно отладки создается отладчиком JIT (Just-In-Time), который входит в состав Visual Studio. Мне придется протестировать программное обеспечение с «гражданской» Windows и посмотреть, не обнаруживаются ли там исключения.

ОБНОВЛЕНИЕ № 3: По какой-то причине Релиз, созданный с помощью Visual Studio, работает, но Релиз, построенный с использованием сценариев MSBuild и Dotfuscator, не работает.

Ответы [ 8 ]

6 голосов
/ 17 сентября 2010

Вы не указали, какую платформу вы используете, но есть другие события «необработанного исключения».

Для Windows Forms есть Application.ThreadException.

Для WPF / Silverlight есть Application.DispatcherUnhandledException.

Сначала попробуйте один из этих двух и сообщите нам, если у вас все еще есть проблемы.

5 голосов
/ 22 сентября 2010

Я наконец решил проблему. Проблема была вызвана не прослушиванием неправильных исключений, а отсутствием DLL в выпущенной версии.

После добавления прослушивателей для событий DispatchedUnhandledException и ThreadException у меня больше не появилось странное всплывающее окно Microsoft .NET Framework, которое позволяло пользователю продолжать запускать программное обеспечение после исключения. Однако моя собственная обработка исключений все еще была прервана.

Поскольку программное обеспечение уже выходило из строя в тот момент, когда должен был сработать обработчик исключений, у меня был перехват (Exception) вокруг обработчика исключений. После удаления этой уловки я наконец-то получил правильное сообщение об ошибке с версией релиза и добавил недостающие библиотеки DLL.

Урок, который я усвоил (опять же): не используйте пустой блок catch (Exception). Это зло.

4 голосов
/ 17 сентября 2010

Звучит так, как будто исключение всплывает в цикле сообщений вашего приложения. В Windows Forms вы можете справиться с ними, настроив обработчик событий для события Application.ThreadException . В WPF / Silverlight эквивалентное событие будет Application.DispatcherUnhandledException .

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

EDIT

В WPF / Silverlight установите e.Handled = true, чтобы исключение продолжало стек.

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

Ой ... Dotfuscator может сгенерировать недопустимую сборку, не поддерживающую JIT.JIT исключения никогда не могут быть перехвачены пользовательским кодом.Это похоже на то, как вы не можете поймать StackOverflowException, потому что среда выполнения не может гарантировать, что он сможет безопасно восстановиться после обнаруженной ошибки.

Тем не менее, очень маловероятно, что вы получите исключение JIT во время выполнения, посколькуразличные этапы проверки между вашим IL и JITer.Может быть, у вас есть InvalidProgramException или BadImageFormatException?Если JITter действительно дает сбой, это, скорее всего, ошибка во время выполнения и не должно произойти.

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

  1. Запустить PEVerify на вашем сломанном /работающей сборки и сравните вывод.
  2. Попробуйте NGEN на вашей сломанной сборке, чтобы проверить, можете ли вы спровоцировать ошибку.
1 голос
/ 04 апреля 2015
// Add the event handler for handling UI thread exceptions to Windows Form Events.
    // Uses SystemThreading.
    // NOTE: Remember to turn Execption Handler OFF in the Debugger for testing!!  Debug -> Common Language Runtime Exceptions -> User-Unhandled -> OFF. 
    // NOTE: A separate Event Handler is Needed for other threads added to the Application.
    // NOTE: Methods can catch, inform, then throw for logging and emailing as well.
    // Add these to Program.cs.
    static void Main()
    {
            Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);

            // Set the unhandled exception mode to force all Windows Forms errors to go through the Handler.
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

           // ...
    }

    // Then put your handler in the method referenced in the event definition above.
    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
         // Your Code ...
    }

  // Sorry for the ragged listing.  Still getting used to the editor here.
1 голос
/ 17 сентября 2010

Можно просмотреть класс AppDomain, событие UnhandledException и событие Application.ThreadException . Они будут перехватывать необработанные исключения, так как для исключений, которые вы обрабатываете сами с помощью блока try-catch, вы можете написать вспомогательный класс для управления вашими исключениями и делать с ними то, что вам нужно. Вы даже можете написать третье событие в этом классе для обработанных исключений.

0 голосов
/ 17 сентября 2010

Из документации события UnhandledException,

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

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

Сначала я поставлю под сомнение необходимость вашего квеста.
Самый простой подход - просто принять групповое соглашение, которое есть в Main и всех функциях потока.включающий try-catch.
Кажется, есть новые типы + события (DispatcherUnhandledException) для перехвата необработанных исключений, но я бы сомневался, стоит ли это сложности, в которую он втягивается. Это должна быть последняя линия защиты, а неосновной.
например, если необработанное исключение возникает в другом потоке, вам понадобится больше кода (поскольку исключения не перенаправляются в потоки, и он просто завершает процесс).

0 голосов
/ 17 сентября 2010

Поможет ли try ... catch блок в Main() помочь?

...