Диагностика вылета программы без дампа по журналу событий Windows
Проблема
Приложение неожиданно завершается (вылетает) без предложения отправить отчет об ошибке разработчикам ЛЭРС УЧЕТ, отображая при этом стандартное окно с надписью "Прекращена работа программы ЛЭРС УЧЕТ - XXX".
Решение
Обычно, такое происходит, если в каком-то потоке программы нет обработчика исключений, либо произошло исключение, после которого, продолжение работы программы невозможно, например StackOverflowException.
В этом случае ОС делает запись в журнале событий Windows "Приложение" с источником "Windows Error Reporting" и уровнем "Сведения".
Содержимое записи выглядит примерно следующим образом:
P1: lers.client.exe // Имя исполняемого файла
P2: 3.8.0.30800 // Версия сборки исполняемого файла (P1)
P3: 53842d91// Дата и время создания исполняемого файла (P1)
P4: Lers.Client // Сборка, в которой произошло исключение
P5: 3.8.0.30800 // Версия сборки (P4), в которой произошло исключение
P6: 53842d91 // Дата и время создания сборки (P4)
P7: 6e // Маркер метода, в котором произошло исключение
P8: b // Смещение IL в методе (P7)
P9: System.InvalidOperationException // Тип исключения
С помощью этой информации можно определить точное место, в котором произошло исключение. Для этого понадобится лишь такая же сборка (P4) нужной версии (P5) и отладчик WinDbg.
Определение места возникновения исключения
- Запустите отладчик WinDbg нужной разрядности (32/64 bit). Через пункт меню File->Open Executable откройте исполняемый файл (P1) точно такой же версии как (P2). Если исключение произошло не в исполняемом файле (P1), то необходимо удостовериться, что в процесс будет загружена сборка (P4) нужной версии (P5).
- Нажмите пункт меню Debug->Go, чтобы запустился процесс. Далее необходимо заставить CLR загрузить сборку (P4) в память, т. е. выполнить действия, которые приведут в вызову какого-либо метода, содержащегося в сборке.
- Загрузите библиотеку SOS для отладки приложений .NET. Чтобы загрузилась правильная библиотека, необходимо использовать команду .loadby, иначе команда !Token2EE может не работать и выдавать ошибку “offset not exist for m_firstBlock. Is the framework loaded yet?”: .loadby sos clr
- Теперь необходимо получить описание метода. Для этого необходимо сначала сложить число 0x06000000 и параметр (P7): 0x0600006e.
И после этого выполнить команду:
!Token2EE lers.client.exe 0600006e
Внимание
имя сборки в этой команде должно содержать расширение. В примерах оно не содержится, но без расширения не работает и ничего не выводит в ответ.
Результат выполнения команды:
Module: 00202eac
Assembly: Lers.Client.exe
Token: 0600006e
MethodDesc: 006313d0 // Адрес описания метода
Name: Lers.MainForm.<barButtonMaps_ItemClick>b__0(System.Object) // Полное название метода,
- На последнем шаге определяем точное место в методе, где произошло исключение. Для этого дизассемблируем код метода с помощью команды:
!dumpil 006313d0
Результат выполнения команды:
ilAddr = 009e322f
IL_0000: nop
IL_0001: ldstr "test"
IL_0006: newobj System.InvalidOperationException::.ctor
IL_000b: throw
С помощью параметра (P8) = b в IL-коде находим нужную строку IL_000b. Это и есть точное место, где произошло исключение.
Список источников
- http://blogs.msdn.com/b/oanapl/archive/2009/01/30/windows-error-reporting-wer-and-clr-integration.aspx
- http://blogs.msdn.com/b/junfeng/archive/2009/07/27/getting-where-the-exception-is-thrown-in-windows-error-report-for-managed-application-without-a-dump.aspx
- http://msdn.microsoft.com/ru-ru/library/bb190764(v=vs.110).aspx