Рихтер Дж., Назар К. - Windows via C C++. Программирование на языке Visual C++ - 2009
.pdf838 Часть V. Структурная обработка исключений
Табл. 26-4. Флаги, связанные с добавляемыми файлами
Флаг |
Описание |
DELETE_WHEN_DONE = 1 |
После отправки отчета файл следует удалить |
ANONYMOUS_DATA = 2 |
Файл не содержит персональной информации, по |
|
которой можно определить пользователя. Если |
|
этот флаг не задан, при первом запросе сервера |
|
Майкрософт на передачу этого файла система |
|
спрашивает разрешение у пользователя. Если |
|
пользователь соглашается, параметру Consent в |
|
системном реестре присевается значение 3. После |
|
этого все файлы, помеченные этим флагом, будут |
|
отправляться без запроса подтверждения у пользо- |
|
вателя |
Зарегистрированные таким образом файлы будут сохранены в отчете. Заметьте, что функцию WerRegisterFile можно вызывать многократно, чтобы добавить к отчету несколько файлов.
Примечание. Число элементов отчета WER, регистрируемых вызовами
WerRegisterMemoryBlock и WerRegisterFile, не может быть больше, чем за-
дано параметром WER_MAX_REGISTERED_ENTRIES (в настоящее время — 512). Возвращаемое в случае этой ошибки значение HRESULT можно сопоставить с кодом ошибки Win32 следующим образом: if ( HRESULT_ CODE(hr) == ERROR_INSUFFICIENT_BUFFER).
В завершение замечу, что для удаления из отчетов блоков данных и файлов служат следующие функции:
HRESULT WerUnregisterMemoryBlock(PVOID pvAddress);
HRESULT WerUnregisterFile(PCWSTR pwzFilePath);
Создание и настройка отчетов о сбоях
В этом разделе я расскажу, как создавать нестандартные отчеты о сбоях в собственных приложениях. Соответствующие функции позволяют создавать отчеты не только о необработанных исключениях, но и о проблемах, никак с ними не связанных. Кроме того, после генерации отчета приложения не обязано завершаться, и может спокойно работать дальше. Так что стоит подумать об использовании службы Windows Error Reporting вместо добавления непонятных сообщений в журнал событий Windows. Однако инфраструктура WER ограничивает число и размеры отчетов посредством параметров системного реестра, расположенных в разделе HKEY_ CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting (табл. 26-5).
|
Глава 26. Отчеты об ошибках и восстановление приложений.docx 839 |
Табл. 26-6. Параметры реестра, управляющие хранением данных WER |
|
Параметр |
Описание |
MaxArchiveCount |
Максимальное число файлов в архиве (допустимые значения — 1-5000; |
|
значение по умолчанию — 1000) |
MaxQueueCount |
Максимальное число отчетов, которое можно поставить в очередь на ло- |
|
кальном компьютере до отправки их в Майкрософт (допустимые значе- |
|
ния — 1-500; значение по умолчанию — 50) |
Примечание. Результаты трассировки отчетов, отправленных в Microsoft (за исключением вложенных в отчет файлов), архивируется в каталоге
AppData\Local\Microsoft\Windows\WER\ReportArchive профиля текущего пользователя. Очередь отчетов, которые еще не отправлены, хранится в папке AppData\Local\Microsoft\Windows\WER\ReportQueue текущего поль-
зователя. К сожалению, API, который консоль WER использует для работы с этими отчетами, не задокументирован, поэтому вы не сможете перебрать отчеты в своем коде. Будем надеяться, что в будущих версиях Windows это изменится.
Создание, настройка и передача отчетов о сбоях службе WER осуществляется путем вызова следующих функций в указанной последовательности:
1.Вызов WerReportCreate создает новый отчет о сбое.
2.Функция WerReportSetParameter служит для настройки параметров отчета.
3.Вызов WerReportAddDump добавляет к отчету мини-дамп.
4.Функция WerReportAddFile добавляет к отчету произвольные файлы (например, пользовательские документы).
5.Функция WerReportSetUIOption модифицирует текст, который отображается пользователю при вызове WerReportSubmit.
6.Вызов WerReportSubmit передает отчет WER. В зависимости от заданных флагов, Windows может поставить запрос в очередь, либо запросить у пользователя подтверждение и отправить отчет в Майкрософт.
7.Вызов WerReportCloseHandle закрывает отчет.
Атеперь разберем эту процедуры подробнее. При чтении следующих разделов вам, возможно, пригодится описание функции GenerateWerReport, применяемой в приложении-примере Customized WER (см. ниже).
После запуска этой программы откройте консоль WER и щелкните ссылку View Problem History, Чтобы получить список отчетов (рис. 26-5).
В записи о сбоях, вызванных программой 23-SEHTerm.exe, имя продукта соответствует имени исполняемого файла программы. В отличие от нее, отчет о сбое 25-HandleUnhandled.exe выводится в секции Wintellect Applications Suite. В
столбце Problem также выводится информация о сбое, но более подробная, чем комментарий по умолчанию «Stopped working».
Если двойным щелчком отрыть подробности отчета, будет видно, что его содержимое также изменено (рис. 26-6) с помощью Wer*-функций (сравните рис.
26-6 и 26-3).
840 Часть V. Структурная обработка исключений
Рис. 26-5. Список отчетов в консоли WER, отсортированный по названию продукта
Заголовок отчета и название сбоя — те же, что в сводке, отображаемой в списке консоли WER. Новое поле Description выводит краткое описание сбоя, а значение Problem Event Name теперь содержит больше полезной информации (а не только строку APPCRASH, как прежде).
Рис. 26-6. Нестандартный отчет в консоли WER
Глава 26. Отчеты об ошибках и восстановление приложений.docx 841
Создание собственного отчета о сбое: функция WerReportCreate
Чтобы создать собственный отчет, вызовите функцию WerReportCreate и передайте ей сведения об отчете, который требуется создать:
HRESULT WerReportCreate(
PCWSTR pwzEventType,
WER_REPORT_TYPE repType,
PWER_REPORT_INFORMATION pReportInformation,
HREPORT *phReport);
Параметр pwzEventType — это Unicode-строка, которая представляет собой первый элемент Problem Signature. Заметьте: чтобы ваш отчет был доступен для просмотра на сайте Windows Quality Web (http://WinQual.Microsoft.com), соответ-
ствующий тип события должен быть зарегистрирован в Майкрософт (подробнее см. в описании WerReportCreate на сайте MSDN по ссылке http://msdn2.microsoft.com/en-us/library/bb513625.aspx).
Внимание! Все Wer*-функции принимают только Unicode-строки, поэтому в их именах нет суффиксов А и W.
Параметр repType принимает значения, перечисленные в табл. 26-6.
Табл. 26-6. Значения параметра repType
Значение |
Описание |
WerReportNonCritical = 0 |
Отчет «молча» добавляется в очередь и отправ- |
|
ляется в Майкрософт согласно значению пара- |
|
метра Consent |
WerReportCritical = 1 |
Отчет добавляется в локальную очередь с уве- |
|
домлением пользователя и, при необходимости, |
|
завершением приложения |
WerReportApplicationCrash = 2 |
Идентичен WerReportCritical, но в уведомлении |
|
пользователя выводится понятное имя приложе- |
|
ния, а не его исполняемого файла |
WerReportApplicationHang = 3 |
Идентичен WerReportApplicationCrash, но ис- |
|
пользуется при зависаниях и взаимных блоки- |
|
ровках |
Параметр pReportInformation указывает на структуру
WER_REPORT_INFORMATION, содержащую Unicode-поля, перечисленные в табл. 26-7.
842 Часть V. Структурная обработка исключений
Табл. 26-7. Поля структуры WER_REPORT_INFORMATION
Поле |
Описание |
wzApplicationName |
Продукт отображается в столбце Problem History консоли |
|
WER и рядом со значком приложения в описании сбоя |
wzApplicationPath |
Содержимое не отображается на локальной системе, но |
|
доступно на сайте Windows Quality |
wzDescription |
Содержимое отображается в поле Problem Description |
wzFriendlyEventName |
Содержимое отображается в поле Event Name секции Prob- |
|
lem Signature отчета |
Как и все Wer*-функции, WerReportCreate возвращает HRESULT и, если вызов завершился успешно, — описатель отчета (в параметр phReport).
Настройка параметров отчета: функция WerReportSetParameter
После поля Problem Event Name, но перед OS Version и Locale ID в секции отчета
Problem Signature содержится набор пар «ключ-значение», которые задают с помощью следующих функций:
HRESULT WerReportSetParameter(
HREPORT hReport,
DWORD dwParamID,
PCWSTR pwzName,
PCWSTR pwzValue);
В параметре hReport передается описатель, ранее полученный вызовом WerReportCreate. Параметр dwParamID задает пару «ключ-значение», которую необходимо определить. Эта функция позволяет определять до 10 пар, которые задаются объявленными в werapi.h макросами WER_P0—WER_P9 (со значениями 0- 9). В параметрах pwzName к pwzValue вы можете передать нужные вам Unicodeстроки.
Заметьте, что при передаче целого числа, которое меньше 0 или больше 9, WerReportSetParameter возвращает E_INYALIDARG. Также нельзя пропускать идентификаторы, то есть, устанавливая WERP2, необходимо также установить WERP1 и WER_P0. Порядок установки не важен, но если вы пропустите идентификатор, вызов WerReportSubmit закончится неудачей и возвратом HRESULT с
значением 0x8008FF05.
По умолчанию, для стандартного отчета WER устанавливает параметры, перечисленные в табл. 26-8.
844Часть V. Структурная обработка исключений
Вэтом примере кода pExceptionInfo задает сведения об исключении, возвращаемые функцией GetExceptionInformation; ту же самую информацию, как правило, передают фильтру исключений. Далее &wei передается параметру pei функции WerReportAddDump. Тип дампа определяется параметрами dumpType и pDumpCustomOptions (подробнее см. в соответствующих статьях MSDN).
Впараметре dwFlags передают 0 или WER_DUMP_NOHEAP_ONQUEUE.
Обычно в мини-дамп включают содержимое кучи, но флаг
WER_DUMP_NOHEAP_ONQUEUE приказывает WerReportAddDump не делать этого. Этот флаг удобен, когда требуется сэкономить место на диске за счет исключения из отчета содержимого кучи.
Добавление к отчету произвольных файлов: функция WerReportAddFile
В разделе о настройке отчетов, я рассказал, как добавить произвольные файлы во все отчеты о сбоях заданного процесса. Однако вызовом функции WerReportAddFile вы можете добавить к отчету изрядное число файлов (даже больше, чем 512):
HRESULT WerReportAddFile(
HREPORT hReport,
PCWSTR pwzFilename,
WER_FILE_TYPE addFileType,
DWORD dwFileFlags);
В параметре hReport передают описатель отчета, к которому следует добавить файл, заданный параметром pwzFilename. Значения параметра addFileType перечислены в табл. 26-9.
Табл. 26-9. Типы добавляемых к отчету файлов
Тип |
Описание |
WerFileTypeMicrodump = 1 |
Пользовательский микро-дамп |
WerFileTypeMinidump = 2 |
Пользовательский мини-дамп |
WerFileTypeHeapdump = 3 |
Пользовательский дамп кучи |
WerFileTypeUserDocument = 4 |
Файл, в котором могут быть конфиденциальные пользова- |
|
тельские данные. По умолчанию такие файлы не отправляют- |
|
ся в Майкрософт, но в будущем планируется открыть к ним |
|
доступ для разработчиков через сайт Windows Quality |
WerFileTypeOther = 5 |
Любой другой файл |
Не путайте флаги WerFileTypeMicrodump, WerFileTypeMinidump и WerFileTypeHeapdump. При отправке отчета на сервер Майкрософт последний вступает в довольно сложный диалог с пользовательским компьютером для согласования списка отправляемых файлов. В некоторых случаях сервер запрашивает файлы дампов. Тогда локальное хранилище использует эти фла-
Глава 26. Отчеты об ошибках и восстановление приложений.docx 845
ги для отбора пользовательских дампов, генерированных приложением без использования функции WerReportAddDump. Дополнительные сведения о коммуникационном протоколе, по которому осуществляется отправка отчетов о сбоях, см. на сайте Windows Quality. Параметр dwFileFlags выполняет те же функции, что и одноименный параметр WerRegisterFile (см. табл. 26-4).
Модификация текста элементов интерфейса: функция
WerReportSetUIOption
Чтобы настроить текст, отображаемый в окне запроса разрешения на отправку отчета WER, вызовите следующую функцию:
HRESULT WerReportSetUIOption(
HREPORT hReport,
WER_REPORT_UI repUITypeID,
PCWSTR pwzValue);
Параметр hReport задает отчет, для которого необходимо модифицировать текст пользовательского интерфейса. Параметр repUITypeID определяет элемент, текст которого требуется изменить, а параметр pwzValue — текст (в формате Unicode), который необходимо вывести в этом элементе интерфейса.
Функцию WerReportSetUIOption следует вызывать для каждого из элементов интерфейса, который вы хотите изменить. Заметьте, что текст некоторых надписей и кнопок изменить невозможно. Примеры изменения текстовых полей показаны на экранных снимках ниже. Дополнительные сведения см. в описании функ-
ции WerReportSetUIOption в документации Platform SDK.
Передача отчета о сбое: функция WerReportSubmit
Теперь можно отправить отчет о сбое, вызвав функцию:
HRESULT WerReportSubmit(
HREPORT hReport,
WER_CONSENT consent,
DWORD dwFlags,
PWER_SUBMIT_RESULT pSubmitResult);
846 Часть V. Структурная обработка исключений
Параметр hReport задает описатель отчета, который требуется передать. Параметр consent принимает одно из следующих значений: WerConsentNotAsked, WerConsentApproved или WerConsentDenied. Как сказано выше, будет ли отчет от-
правлен в Майкрософт, зависит от значения параметра Consent в системном реестре, но окна, которые открывает WER при передаче отчета, определяются одноименным параметром функции WerReportSubmit. Если он равен
WerConsentDenied, отчет не отправляется, а если WerConsentApproved — откры-
ваются стандартные окна с уведомлениями о генерации отправке отчетов (рис. 25- 2 и 25-3). Если параметру consent присваивается значение WerConsentNotAsked, а одноименный параметр реестра равен 1 (то есть, система всегда должна запрашивать у пользователя разрешение, см. рис. 25-5), открывается окно, показанное на рис. 25-6. При этом пользователь должен сам решить, следует ли отправлять отчет о сбое в Майкрософт для поиска способа его устранения либо выбрать отладку или завершение приложения. Параметр dwFlags — это битовая маска, описанная в табл. 26-10.
Табл. 26-10. Параметры передачи отчета о сбое
Параметр |
Описание |
HONOR_RECOVERY = 1 |
Разрешает восстановление после критических сбоев (см. |
|
ниже) |
HONOR_RESTART = 2 |
Разрешает перезапуск приложения после критических |
|
сбоев (см. ниже) |
SHOW_DEBUG = 8 |
Если этот флаг не установлен, кнопка Debug не отобража- |
|
ется |
NO_CLOSE_UI = 64 |
Кнопка Close не отображается |
START_MINIMIZED = 512 |
Окно уведомления открывается в свернутом виде и мигает |
|
на панели задач Windows |
QUEUE = 4 |
Отчет ставится в очередь без уведомления. Если в реестре |
|
Consent = 1, отчет генерируется, но не отправляется в |
|
Майкрософт |
NO_QUEUE = 128 |
Запрещает постановку отчета в очередь |
NO_ARCHIVE = 256 |
Передает обработку отчета другому процессу |
|
(wermgr.exe) |
OUTOFPROCESS_ASYNC = 1024 |
Передает обработку отчета другому процессу |
|
(wermgr.exe), после чего WerReportSubmit немедленно |
|
возвращает управление, не дожидаясь завершения обра- |
|
ботки |
ADD REGISTERED DATA = 16 |
Добавляет к отчету зарегистрированные данные. Заметь- |
|
те, что если это флаг установлен вместе с флагом, пере- |
|
дающим обработку отчета другому процессу, добавлен- |
|
ные с помощью функции WerRegisterFile файлы попадут в |
|
отчет дважды. Эта ошибка будет устранена в будущих |
|
версиях Windows |
Глава 26. Отчеты об ошибках и восстановление приложений.docx 847
Об успешном или неудачном завершении вызова WerReportSubmit сообщает возвращаемое ей значение HRESULT. Однако, собственно, результат возвращается в параметре pSubmitResult как ссылка на переменную WER_SUBMIT_RESULT (подробнее об этом см. в документации MSDN). Параметр pSubmitResult бесполезен, только когда в dwFlags установлен флаг
WER_SUBMIT_OUTOFPROCESS_ASYNC. В этом случае WerReportSubmit воз-
вращает управление до завершения обработки запросов. Ясно, что использовать этот флаг следует с осторожностью и ни в коем случае не применять его в контексте необработанного исключения: процесс будет закрыт прежде, чем завершится создание и отправка отчета. Этот флаг предназначен для генерации отчетов в случаях, когда в программе нет необработанных исключений, и ее исполнение нежелательно задерживать до завершения создания отчета. Флаг
WER_SUBMIT_OUTOFPROCESS_ASYNC обычно применяется для процессов,
отслеживающих возникновение сбоев в других процессах. Например, Service Control Manager (SCM) в Windows использует этот флаг для уведомления о зависании процессов служб.
Закрытие отчета о сбое: функция WerReportCloseHandle
После отправки отчета не забудьте передать его описатель функции WerReportCloseHandle, чтобы освободить связанные с ним внутренние структуры данных:
HRESULT WerReportCloseHandle(HREPORT hReportHandle);
Программа-пример Customized WER
Эта программа (26-CustomizedWER.exe) демонстрирует создание отчетов о сбоях при возникновении необработанного исключения. На ее примере я также показываю прием, гарантирующий исполнение кода в блоке finally. Эта программа изменяет стандартный интерфейс WER и выводит собственное окно, в котором пользователь может выбрать между закрытием приложения и его отладкой. Изменив этот код, можно по умолчанию лишить пользователя возможности выбора отладки, а также создать локализованные версии окон WER для языка интерфейса приложения (а не операционной системы). Файлы исходного кода и ресурсов этой программы находятся в каталоге 26-CustomizedWER внутри архива, доступного на веб-сайте поддержки этой книги.
Примечание. Если ваше приложение должно работать в версиях Windows, предшествующих Vista, используйте функцию ReportFault. У этой функции намного меньше возможностей, чем у вышеописанных Wer*-функций. В приложениях для Windows Vista использовать ReportFault не рекомендуется.