Перезапуск приложения в случае его аварийного завершения
Перезапуск приложения в случае его аварийного завершения
Небольшое дополнение к статье про обработку критических ошибок. Обработать возникшую ошибку, сохранить в лог состояние регистров на момент падения, уведомить пользователя о произошедшем - это хорошо и правильно. Но в Windows есть еще один интересный механизм обработки критических ошибок. Речь идет об автоматическом перезапуске приложения в случае возникновения нештатной ситуации типа необрабатываемого исключения или безответного зависания.
Делается это при помощи штатной функции RegisterApplicationRestart, которая доступна для использования, начиная с Windows Vista. Первым параметром указывается юникодная строка, которая будет передана в качестве параметра при перезапуске, причем юникодной она должна быть независимо от кодировки самого приложения. Вторым параметром можно настроить ситуации, при которых перезапуск выполняться не будет. Например, можно оставить только возможность перезапуска при зависании, а всякие деления на ноль, запись в запрещенные участки памяти и т.п. обрабатывать уже известными нам способами. Через параметры командной строки можно уведомлять приложение, что оно было перезапущено после аварийного завершения, тем самым давая возможность как-то реагировать на произошедшее. Например:
Code (Assembler) : Убрать нумерацию
- ; Параметры командной строки на каждый из случаев возможного падения
- szCmd1 du '/error:MarlesonOne',0
- szCmd2 du '/error:MarlesonTwo',0
- ...
- ...
- ; Первая часть Марлезонского балета
- invoke RegisterApplicationRestart,szCmd1,0
- ...
- ; Какие-то действия с возможностью падения
- ...
- ; Вторая часть Марлезонского балета
- invoke RegisterApplicationRestart,szCmd2,0
- ...
- ; Еще немного действий с возможностью падения
- ...
- ; Все самое страшное уже позади
- invoke UnregisterApplicationRestart
Важное замечание. Возможность перезапуска у приложения появляется только в том случае, если оно отработало уже не менее 60 секунд. Это сделано специально, чтобы не нагружать систему постоянными перезапусками кривого приложения, которое валится еще при старте.
Перезапуск приложения при зависании
В случае безответного зависания приложения и при выполнении условия 60 секунд, приложение не перезапускается автоматически, а просто в меню выбора возможных действий пользователя добавляется еще один пункт "Перезапустить программу".
Командная строка - не единственный способ передать программе информацию о перезапуске. С помощью вызова RegisterApplicationRecoveryCallback можно задать callback-функцию, которая получит управление перед тем, как приложение перезапустится. Одним из параметров при установке callback-функции является время, отводимое на восстановление, по умолчанию это 5 секунд, но не более 5 минут. Во время процесса восстановления приложение должно вызывать функцию ApplicationRecoveryInProgress в течение указанного интервала, чтобы сигнализировать системе, что программе еще требуется время. Когда все восстановительные операции выполнены, приложение должно вызвать функцию ApplicationRecoveryFinished, чтобы система зря не тратила время на ожидание.
Code (Assembler) : Убрать нумерацию
- ; Зарегистрировать callback-функцию для перезапуска
- ; и отвести на восстановление 60 секунд
- invoke RegisterApplicationRecoveryCallback,\
- ApplicationRecoveryCallback,NULL,60000,NULL
- ...
- ...
- ;--------------------------------------------------------------------
- ; Callback-функция, которая вызывается при перезапуске программы
- ;--------------------------------------------------------------------
- proc ApplicationRecoveryCallback pvParameter:DWORD
- ; Сигнализировать системе, что процесс восстановления запущен
- invoke ApplicationRecoveryInProgress,tmp
- or eax,eax
- jz @f
- ; Возникла ошибка, прервать восстановление
- invoke ApplicationRecoveryFinished,FALSE
- jmp .loc_ret
- @@:
- ; Восстановление отменено пользователем
- cmp [tmp],TRUE
- je .loc_ret
- ; ... запустить процесс восстановления ...
- ; Сигнализировать системе, что процесс восстановления окончен
- invoke ApplicationRecoveryFinished,TRUE
- .loc_ret:
- ret
- endp
Просмотров: 1874 | Комментариев: 5
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(15.07.2021 в 10:31):
Бесполезной ее делает бездумное использование. А так это отличный инструмент для обработки ошибок с возможностью получать репорты от пользователей.
Малькодор
(15.07.2021 в 08:32):
Интересная штука, но
> а просто в меню выбора возможных действий пользователя добавляется еще один пункт "Перезапустить программу"
делает фичу практически бесполезной на мой взгляд
> а просто в меню выбора возможных действий пользователя добавляется еще один пункт "Перезапустить программу"
делает фичу практически бесполезной на мой взгляд
Petya
(07.04.2021 в 17:19):
А, не заметил. Тогда может пригодиться.
ManHunter
(07.04.2021 в 17:15):
Как минимум через SEH/VEH не обработать безответное зависание.
Petya
(07.04.2021 в 17:12):
А есть принципиальные отличия от оборачивания всего в SEH/VEH?
Добавить комментарий
Заполните форму для добавления комментария