Необработени изключения от управляван потребителски контрол на C#, използван в диалоговия прозорец на MFC

Нашето основно приложение е изградено в MFC C++, но ние се опитваме да напишем нов код в .NET и сме създали потребителска контрола в .NET, която ще се използва в съществуващ диалогов прозорец на MFC.

Въпреки това, когато неочаквано/необработено изключение бъде хвърлено от потребителския контрол, това води до срив на приложението MFC (незаконен операционен стил), без възможност за възстановяване.

добавих

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);

Към конструктора на потребителския контрол на .NET, но изглежда не улавя нищо.

Има ли някакъв начин да добавите събитие в MFC, за да се справите с тях?

Quick google не върна нищо полезно.

Благодаря.


Редактиране: Все още не успях да разреша това по начина, по който бих искал, изглежда като най-добрият начин да го направя, е да се опитате да обхванете целия .NET код, така че да няма изключения .


person PostMan    schedule 27.07.2009    source източник
comment
Проверете редакцията ми. Използвам го във всеки манипулатор на събития; и ти можеш.   -  person John Saunders    schedule 27.07.2009
comment
Трябва само да опитате/хванете около най-външния код на .NET - манипулаторите на събития и публичните входни точки.   -  person John Saunders    schedule 01.08.2009
comment
О, да, това е, което трябваше да направя, но то покрива целия код на .NET, пряко или косвено.   -  person PostMan    schedule 03.08.2009


Отговори (4)


Зададох същия въпрос преди известно време: Последно управлявано изключение манипулатор в смесен собствен/управляван изпълним файл?

Това, което открих, е, че управляваните необработени изключения се задействат САМО когато се изпълняват в управлявана нишка. Управляваният WndProc е мястото, където се случва магията.

Имате няколко опции: можете да поставите замяна на ниско ниво в CWinApp и да хванете Exception^. Това може да има непредвидени странични ефекти. Или можете да отидете със структурирана обработка на изключения (SEH), която ще ви даде хакване на /всички/ необработени изключения. Това не е лесен път.

person Aidan Ryan    schedule 27.07.2009

Мисля, че искате да имате манипулатора на необработени изключения в MFC страната на нещата:

AppDomain::CurrentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(&CurrentDomain_UnhandledException);

[същото за Application.ThreadException]

Разгледайте този подобен въпрос във форумите на MSDN: Необработено изключение в приложение за смесен режим

person Judah Gabriel Himango    schedule 27.07.2009
comment
Кодът в предоставената връзка всъщност не работи, нито предоставеният пример за съжаление. Компилира 100%, но все още същият резултат - person PostMan; 27.07.2009
comment
Наистина, това не работи. Освен това защо контекстът, в който протича регистрацията на събитието, би имал някакъв ефект върху регистрацията? Нишката, която сте свързали, има приет лош отговор, по-късните отговори потвърждават проблема на този питащ. - person Aidan Ryan; 27.07.2009

Разбира се, по-добрата идея би била или да обработите изключението в C# кода, или иначе да разберете какво го причинява и да го поправите, така че изключението никога да не се хвърля. Какво пречи на това?

Във всеки манипулатор на събития на потребителския контрол поставете блок try/catch:

private void btnOk_Click(object sender, EventArgs e) {
    try {
        // real code here
    }
    catch (Exception ex) {
        LogException(ex);
        // do whatever you must in order to shut down the control, maybe just
    }
}

Ето какво използвам:

public static class UI
{
    public static void PerformUIAction(Control form, Action action)
    {
        PerformUIAction(form, action, (string) null);
    }

    public static void PerformUIAction(
        Control form, Action action, string message)
    {
        PerformUIAction(form, action, () => message);
    }

    public static void PerformUIAction(
        Control form, Action action, Func<string> messageHandler)
    {
        var saveCursor = form.Cursor;
        form.Cursor = Cursors.WaitCursor;
        try
        {
            action();
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                messageHandler() ?? ex.Message, "Exception!",
                MessageBoxButtons.OK, MessageBoxIcon.Error,
                MessageBoxDefaultButton.Button1,
                MessageBoxOptions.DefaultDesktopOnly);
            Debug.WriteLine(ex.ToString(), "Exception");
            throw;
        }
        finally
        {
            form.Cursor = saveCursor;
        }
    }
}

Аз го наричам така:

private void _copyButton_Click(object sender, EventArgs e)
{
    UI.PerformUIAction(
        this, () =>
                  {
                  // Your code here
                  });
}
person John Saunders    schedule 27.07.2009
comment
Това с изключенията е, че не знаем кога идват или защо. Така че това не е възможно. И също така потребителският контрол има доста събития и методи. Кодирах изключенията, които са възможни, но искам да хвана другите - person PostMan; 27.07.2009
comment
Изглежда, че това е доста работа и наистина се нуждая от решение, което не изисква от мен да добавям допълнителен код всеки път, когато трябва да хвана изключение (освен тези, които мога да очаквам) - person PostMan; 28.07.2009
comment
Както искаш. Но забележете, че добавяте три реда код след отворения { и един ред преди края }. Можете да направите това с помощта на търсене и замяна, ако нямате нищо против някои прости регулярни изрази. Освен това може да не сте забелязали; можете да получите достъп до sender и e вътре в блока your code here. Кодът, който опаковате, не се променя. - person John Saunders; 28.07.2009
comment
Не ме разбирайте погрешно, това е страхотно решение, но за съжаление не отговаря на проблема ми. Ако можех да публикувам още код, щях да го направя, но тъй като е свързан с работата и всичко останало. - person PostMan; 28.07.2009
comment
Няма проблем. Не се обиждам. :-) Ще ми е любопитно да разбера за каква ситуация този модел не пасва, просто защото е пасвал на толкова много ситуации през годините. За първи път го използвах с .NET 1.1, където трябваше да използвате изрични имена на методи за делегати. Това беше грозно! Ламбдите решават всички проблеми, които имах от 2003 г. насам! - person John Saunders; 28.07.2009

Проблемът ми е разрешен. Имах asp:table на моята ASPX страница и без контейнер. Премахнах asp:table и го замених с контейнера и изчистих контролите всеки път, когато генерирам таблицата. Сега работи перфектно. Благодаря за помощта.
person Judah Gabriel Himango    schedule 27.07.2009
comment
Интересна идея, моля, споделете резултата, ако опитате. - person Aidan Ryan; 27.07.2009
comment

Rainbow Tables основно позволяват на някой да съхранява голям брой предварително изчислени хешове.

Това улеснява разбиването на вашите хеширани пароли, тъй като вместо да изпълнява цяла купчина функции за хеширане, работата вече е свършена и те на практика просто трябва да направят справка в база данни.

Най-добрата защита срещу този вид атака е да използвате сол (произволни знаци) в паролата си. т.е. вместо да съхранявате md5(парола), съхранявайте md5(парола + сол) или дори по-добре md5(сол + md5(парола)).

Тъй като дори и с таблици на дъгата, ще бъде почти невъзможно да се съхранят всички възможни солени хешове.

Между другото, очевидно трябва да съхранявате солта си с вашия хеш, за да можете да удостоверите потребителя.

- person PostMan; 28.07.2009
comment
Имайте това от страна на MFC. Ще трябва вашият C++ код да бъде компилиран като C++/CLI (управляван C++ код). - person Judah Gabriel Himango; 28.07.2009