Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Создание эффективных приложений для Windows Джеффри Рихтер 2004 (Книга).pdf
Скачиваний:
385
Добавлен:
15.06.2014
Размер:
8.44 Mб
Скачать

Переход события в свободное состояние пробуждает поток отлаживаемого про цесса, и он передает отладчику информацию о необработанном исключении. Полу чив эти данные, отладчик загружает соответствующий файл исходного кода и Пере ходит к команде, которая вызвала исключение. Вот это дейстничельно круто!

Кстати, совсем не обязательно дожидаться исключения, чгобы начать отладку. Отладчик можно подключить в любой момент командой "MSDEV -p PID", где PID — идентификатор отлаживаемого процесса. Task Manager в Windows 2000 еще больше упрощает эту задачу. Открыв вкладку Process, Вы можете щелкнуть строку с нужным процессом правой кнопкой мыши и выбрать из контекстного меню команду Debug. В ответ Task Managcr обратится к только что рассмотренному разделу реестра и вы зовет CreatуProcess, передав ей идентификатор выбранного процесса Но вместо опи сателя события Task Manager передаст 0.

Отключение вывода сообщений об исключении

Иногда нужно, чтобы окно с сообщением об исключении нс появлялось на экране, — например, в готовом программном продукте. Ведь если такое окно появится, пользо ватель может случайно перейти в режим отладки Вашей программы. Стоит ему толь ко щелкнуть кнопку Cancel, и он шагнет на незнакомую и страшную территорию попадет в отладчик. Поэтому предусмотрено несколько способов, позволяющих из бежать появления этого окна на экране.

Принудительное завершение процесса

Запретить функции UnhandledExceptionFilter вывод окна с сообщением об исключе нии можно вызовом SetErrorMode с передачей идентификатора SEM_NOGPFAULT

ERKORBOX:

UINT SetErrorMode(UINT fuErrorMode);

Тогда UnhandledExceptionFilter, вызванная для обработки исключения, немедлен но вернет EXCEPTION_EXECUTE_HANDLER, что приведет к глобальной раскрутке и выполнению обработчика в BaseProcessStart или BaseThreudStart, который закроет процесс.

Лично мне этот способ не нравится, так как пользователь нс получает никакого предупреждения — приложение просто исчезает.

Создание оболочки вокруг функции потока

Другой способ состоит в том, что Вы помещаете входную функцию первичного по тока

(main, wmain, WinMain или wWinMairi) в блок try-except. Фильтр исключений дол жен всегда возвращать EXCEPTION_EXECUTE_HANDLER, чтобы исключение действи тельно обрабатывалось; это предотвратит вызов UnbandledExceptionFilter.

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

Этому способу присущ один недостаток: он позволяет перехватывать только те исключения, которые возникают в первичном потоке Если исключение происходит в любом другом потоке процесса, система вызывает функцию UnhandledExceptionFilter. Чтобы вывернуться из этой ситуации, придется также включить блоки try-except во входные функции всех вторичных потоков Вашего процесса.

Создание оболочки вокруг всех функций потоков

Функция SetUnhandledExceptionFilter позволяет включать все функции потоков в SEH фрейм:

PTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(

PTOP_LEVEL_EXCEPTION_FILTER pTopLevelExceptionFilter);

После ее вызова необработанное исключение, возникшее в любом из потоков процесса, приведет к вызову Вашего фильтра исключений Адрес фильтра следует передать в единственном параметре функции SetUnhandledExceptionFilter. Прототип этой функциифильтра должен выглядеть так:

LONG UnhandledExceptionFilter(PEXCEPTION_POINTCRS pExceptionInfo);

По форме она идентична функции UnhandledExceptionFilter Внутри фильтра мож но проводить любую обработку, а возвращаемым значением должен быть один из трех идентификаторов типа EXCEPTION_*. В следующей таблице описано, что происходит в случае возврата каждого из идентификаторов.

Идентификатор

Действие

 

 

EXCEPTION_EXECUTE_HANDLER

Процесс просто завершается, так как система

 

не выполняет никаких операций в своем

 

обработчи ке исключений

 

 

EXCEPTION_CONTINUE_EXECUTION

Выполнение продолжается с инструкции,

 

выгнав шей исключение; Вы можете

 

модифицировать ин формацию об

 

исключении, па которую указывает параметр

 

типа PEXCEPTION_POINTERS

EXCEPTION_CONTINUE_SEARCH

Выполняется обычная Windows-функция

 

UnhandledExceptionFilter

 

 

Чтобы функция UnhandledExceptionFilter вновь стала фильтром по умолчанию, вызовите SetUnhandledExceptinnFilter со значением NULL, Заметьте также, что всякий раз, когда устанавливается новый фильтр для необработанных исключений, SetUnhandledExceptionFilter возвращает адрес ранее установленного фильтра. Если таким фильтром была UnhandledExceptionFilter, возвращается NULL. Если Ваш фильтр возвра щает EXCEPTION_CONTINUE_SEARCH, Вы должны вызывать ранее установленный фильтр, адрес которого вернула SetUnbandledExceptionFilter.

Автоматический вызов отладчика

Это последний способ отключения окна с сообщением об исключении. В уже упомя нутом разделе реестра есть еще один параметр — Auto; его значение может быть либо 0, либо 1, В последнем случае UnhandledExceptionFilter не выводит окно, но сра зу же