Как отключить обработку исключений .NET Framework и использовать вместо нее мою собственную?

#c# #.net #windows #exception

#c# #.net #Windows #исключение

Вопрос:

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

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

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

 AppDomain.CurrentDomain.UnhandledException  = CurrentDomain_UnhandledException;
  

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

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

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

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

Комментарии:

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

2. Я пока не смог решить проблему. Я опубликую ответ здесь, когда сделаю это.

Ответ №1:

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

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

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

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

Ответ №2:

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

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

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

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

Ответ №3:

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

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

Редактировать

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

Ответ №4:

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

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

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

  1. Запустите PEVerify на вашей сломанной / рабочей сборке и сравните результат.
  2. Попробуйте NGEN на вашей сломанной сборке, чтобы посмотреть, можете ли вы спровоцировать ошибку.

Ответ №5:

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

Комментарии:

1. они говорят AppDomain. Необработанное исключение предназначено для исключений, которые вы можете только регистрировать. то есть вы не можете исправить? но вы все равно можете выполнить e.Handled = true

Ответ №6:

 // 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.
  

Ответ №7:

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

Комментарии:

1. это не помогло бы устранить необработанные исключения в других потоках.

Ответ №8:

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

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

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

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