Во всех разрабатываемых мною приложениях WPF есть глобальный обработчик исключений, подписанный на AppDomain.CurrentDomain.UnhandledException
, который регистрирует все, что может найти, а затем отображает диалоговое окно, в котором пользователю предлагается связаться с автором, где находится файл журнала и т. Д. Это работает чрезвычайно Ну, и я, и клиенты очень довольны, потому что это позволяет быстро решать проблемы.
Однако при разработке смешанного приложения WPF / C # / CLI / C ++ иногда возникают сбои приложения, которые не попадают в вышеупомянутый обработчик исключений. Вместо этого появляется стандартное диалоговое окно с надписью «ХХХ перестал работать». В деталях это показывает, например,
Problem Event Name: BEX
Application Name: XXX.exe
Fault Module Name: clr.dll
...
Это в основном происходит при обратном вызове управляемой функции из неуправляемого кода и когда эта функция обновляет экран. Мне не потребовалось много времени, чтобы выяснить первопричину проблемы, но только потому, что я могу воспроизвести сбой на моей машине и подключить отладчик: во всех случаях нативный поток все еще находился в точке вызова указателя функции на управляемый делегат, вызывающий напрямую в код C # / WPF.
Настоящая проблема может возникнуть, когда это происходит на клиентском компьютере: учитывая, что обычно клиенты не являются лучшими репортёрами ошибок, может потребоваться очень и очень много времени, чтобы выяснить, что не так, когда все, что они могут предоставить мне, это детали выше.
Вопрос: что я могу сделать, чтобы получить больше информации о сбоях, подобных этим? Есть ли способ получить исключение, подобное этому вызову пользовательского обработчика ошибок в любом случае? Или получить дамп процесса? При загрузке символов для msvcr100_clr0004.dll и clr.dll (загруженных в потоке, где происходит разрыв), стек вызовов выглядит следующим образом:
msvcr100_clr0400.dll!__crt_debugger_hook()
clr.dll!___report_gsfailure() + 0xeb bytes
clr.dll!_DoJITFailFast@0() + 0x8 bytes
clr.dll!CrawlFrame::CheckGSCookies() + 0x2c3b72 bytes
Могу ли я каким-то образом подключить некоторый нативный код C ++ к __crt_debugger_hook () (например, для написания минидампа)? Что приводит меня к дополнительному вопросу: как CheckGSCookies
ведет себя на машине без установленного отладчика, будет ли он вызывать тот же код?
обновление некоторые пояснения к коду: нативный C ++ вызывает делегат CLI (для которого указатель нативной функции получается с помощью GetFunctionPointerForDelegate
, который, в свою очередь, вызывает C # System.Action. Это действие обновляет строку (привязанный к метке WPF) и вызывает событие, измененное свойством, которое вызывает переполнение буфера (при очень быстром обновлении) в безымянном потоке, который не был создан непосредственно в моем коде.
обновление изучая SetUnhandledExceptionFilter
, который сначала ничего не делал, я нашел эту изящную статью , объясняющую, как перехватить любое исключение. Это работает, и я смог записать мини-дамп в фильтр исключений, установленный с помощью этой процедуры. Дамп дает в основном ту же информацию, что и перехватчик отладчика: реальная проблема заключается в том, что строка состояния перезаписывается (вызывается из собственного потока) и одновременно читается из потока пользовательского интерфейса. Все это хорошо, но для этого требуется перехват DLL, что не является моим любимым методом решения проблем. Другой способ все еще был бы хорош.