Подтвердить что ты не робот

Как заставить WinForms молча игнорировать необработанные исключения?

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

Короче говоря, в WinForms, насколько это невероятно, если возникает исключение, библиотека WinForms игнорирует его. Нет "произошло необработанное исключение". Выдается сообщение JIT, оно просто прекращает обработку текущего события и возвращается к графическому интерфейсу.

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

Чтобы увидеть это в действии, я создал совершенно новое приложение WinForms и ввел следующий код:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        string blah = null;
        blah.Trim();
    }
}

Нажмите F5 и загрузите форму без каких-либо ошибок, даже если выбрана нулевая ссылка.

Затем я попытался перейти к основному методу Program.cs и добавить к нему Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);. Тем не менее моя форма загружается, не вызывая никаких ошибок.

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

Кто-нибудь знает, как это сделать?


Обновление: Просто обновляйте все, что я узнал из комментариев.

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

Здравствуйте,

Эта ошибка была закрыта как "Внешняя", поскольку это поведение объясняется тем, как x64 версия Windows обрабатывает исключения. Когда исключение пользовательского режима пересекает переход ядра, x64 версии Windows не позволяют распространению исключения. Поэтому прикрепленные отладчики не знают о том, что произошло исключение, в результате чего отладчик не смог сломать необработанное исключение.

К сожалению, ничто из того, что команда Visual Studo не может сделать для решения этой проблемы, является результатом разработки операционной системы. Все отзывы по этому вопросу должны быть адресованы команде Windows; однако команда Windows считает, что это "правильный" дизайн операционной системы, и считает поведение x86 "неправильным".

С наилучшими пожеланиями, Отладчик Visual Studio

Считая, что сборки, которые не запускаются через визуальную студию (или используя Ctrl + F5 для запуска), похоже, показывают окно сообщения JIT exception EXCEPT, если в вашем Program.cs:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

Этот код заставит окна игнорировать исключение.

Однако, если вы (вместо этого) подписываетесь на событие Application.ThreadException, будут исключены не только ваши исключения, отладчик visual studio будет разбиваться на необработанные исключения!

4b9b3361

Ответ 1

В основной функции Program.cs вы также должны убедиться, что вы завернули свой вызов, чтобы открыть форму в try/catch. Кроме того, используйте AppDomain.UnhandledException для исключения исключений. Мы также добавляем Application.ThreadException.

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

static void Main()
{
    try
    {
        System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandedException);
        AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;

        var form = new MainForm();
        form.ShowDialog();
    }
    catch (Exception e)
    {
        HandleUnhandledException(e);
    }
    finally
    {
        // Do stuff
    }
}

private static void HandleUnhandledException(Object o)
{
    // TODO: Log it!
    Exception e = o as Exception;

    if (e != null)
    {

    }
}

private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
{
    HandleUnhandledException(e.ExceptionObject);
}

private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
    HandleUnhandledException(e.Exception);
}

Ответ 2

Попробуйте следующее.

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

Это фрагмент кода:

[STAThread]
public static void Main(string[] args)
{
    try
    {
        Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
        //your program entry point
    }
    catch (Exception ex)
    {
       //manage also these exceptions
    }
}

private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
    ProcessException(e.Exception);
}

Ответ 3

Легкое исправление не запускается под отладчиком.

Отладчик по какой-то причине маскирует исключение. Если вы обычно запускаете приложение (Ctrl + F5), вы получите обычное "Необработанное исключение" в вашем приложении... Продолжить/выйти? " диалоговое окно.

Ответ 4

Испытывая это часто и выявляя проблему, связанную с 64-битной ОС и событием Form.Load, я всегда делаю все возможное, чтобы выполнять все мои функции запуска в событии Form.Shown. Для всех практических целей это одно и то же (кроме нескольких редких исключительных обстоятельств), и сообщение JIT создается в событии Shown.