Blog. Just Blog

Перехват и блокировка завершения работы Windows

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Перехват и блокировка завершения работы Windows
Перехват и блокировка завершения работы Windows

В статье про отключение перезагрузки при установке обновлений, я упомянул программу ShutdownGuard, которая не дает перезагружаться компьютеру. Мне стало очень интересно, каким образом можно из своего приложения перехватить и заблокировать перезагрузку или выключение компьютера, а также каким образом система завершает работу. Результаты исследований вы можете прочитать в этой статье.

Сперва система перебирает все процессы в сеансе активного пользователя. Очередность перебора процессов определяется параметрами выключения, которые можно установить при помощи функции SetProcessShutdownParameters. Если у процесса имеется top-level окно, то ему посылается сообщение WM_QUERYENDSESSION. Именно на этом этапе приложение может заблокировать завершение работы системы, для этого окно должно вернуть FALSE. Опционально приложение может с помощью функции ShutdownBlockReasonCreate установить текстовую строку, которая будет сообщать пользователю причину блокировки. В обработчике окна это выглядит примерно так:
  1. ; Юникодная строка сообщения о причине блокировки
  2. wString du 'Shutdown blocked!',0
  3.  
  4.         ; Обработка сообщения WM_QUERYENDSESSION
  5.         cmp     [msg],WM_QUERYENDSESSION
  6.         je      .wm_queryendsession
  7.         ...
  8. .wm_queryendsession:
  9.         ; Установить строку блокировки и заблокировать завершение работы
  10.         invoke  ShutdownBlockReasonCreate,[hwnddlg],wString
  11.         invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,FALSE
  12.         ...
Важные замечания. Приложение должно ответить на сообщение WM_QUERYENDSESSION в течение 5 секунд, иначе система принудительно завершит его. Строка блокировки обязательно должна быть в юникоде.

Если хоть одно приложение заблокировало завершение работы, система останавливает процесс завершения работы, выводит пользователю список блокирующих приложений и начинает отсылать им сообщение WM_ENDSESSION с указанием завершить свою работу. Если, по мнению приложения, работу системы завершать все равно нельзя, оно должно на это сообщение точно так же отвечать FALSE. Время для ответа ограничено 5 секундами, иначе приложение будет принудительно завершено.
  1.         ; Обработка сообщения WM_ENDSESSION
  2.         cmp     [msg],WM_ENDSESSION
  3.         je      .wm_endsession
  4.         ...
  5. .wm_endsession:
  6.         ; Заблокировать завершение работы
  7.         invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,FALSE
  8.         ...
Если все необходимые операции закончены, приложение должно удалить строку блокировки при помощи функции ShutdownBlockReasonDestroy и вернуть TRUE в ответ на сообщение системы WM_ENDSESSION.
  1.         ; Обработка сообщения WM_ENDSESSION
  2.         cmp     [msg],WM_ENDSESSION
  3.         je      .wm_endsession
  4.         ...
  5. .wm_endsession:
  6.         ; Удалить строку блокировки и разрешить завершение работы
  7.         invoke  ShutdownBlockReasonDestroy,[hwnddlg]
  8.         invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,TRUE
  9.         ...
Если в задачи приложения не входит непосредственно блокировка завершения работы системы, оно должно действовать следующим образом. На сообщение WM_QUERYENDSESSION отвечает FALSE, чтобы не допустить принудительного завершения, но начинает подготовительные работы: закрывает соединение с базой данных, сохраняет конфиги, логи и т.п. Все это время обработчик сообщения WM_ENDSESSION также должен возвращать FALSE. Как только все финальные работы закончены, приложение должно самостоятельно завершиться.

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

Нормальное завершение работы
СообщениеПриложение
Приложение имеет видимое top-level окно или установило строку с причиной блокировкиУ приложения нет видимых окон и строка блокировки не установлена
WM_QUERYENDSESSIONУ приложения есть неограниченное время, чтобы ответить на сообщение WM_QUERYENDSESSION. Windows через 5 секунд открывает окно со списком приложений, блокирующих завершение работы.У приложения есть 5 секунд, чтобы ответить на сообщение WM_QUERYENDSESSION, иначе Windows принудительно завершит его работу.
WM_QUERYENDSESSIONWindows отображает окно со списком блокирующих приложений, если приложение ответило FALSE на предыдущее сообщение WM_QUERYENDSESSION.Windows отправляет сообщение WM_ENDSESSION приложению, если оно ответило FALSE на предыдущее сообщение WM_QUERYENDSESSION.
WM_ENDSESSIONУ приложения есть неограниченное время, чтобы ответить на сообщение WM_ENDSESSION. Windows через 5 секунд открывает окно со списком приложений, блокирующих завершение работы.У приложения есть 5 секунд, чтобы ответить на сообщение WM_ENDSESSION, иначе Windows принудительно завершит его работу.

Критическое завершение работы
СообщениеПриложение
Приложение имеет видимое top-level окно или установило строку с причиной блокировкиУ приложения нет видимых окон и строка блокировки не установлена
WM_QUERYENDSESSIONУ приложения есть 1 секунда, чтобы ответить на сообщение WM_QUERYENDSESSION, иначе Windows принудительно завершит его работу.У приложения есть 1 секунда, чтобы ответить на сообщение WM_QUERYENDSESSION, иначе Windows принудительно завершит его работу.
WM_QUERYENDSESSIONWindows отправляет сообщение WM_ENDSESSION приложению, если оно ответило FALSE на предыдущее сообщение WM_QUERYENDSESSION.Windows отправляет сообщение WM_ENDSESSION приложению, если оно ответило FALSE на предыдущее сообщение WM_QUERYENDSESSION.
WM_ENDSESSIONУ приложения есть 30 секунд, чтобы ответить на сообщение WM_ENDSESSION, иначе Windows принудительно завершит его работу.У приложения есть 5 секунд, чтобы ответить на сообщение WM_ENDSESSION, иначе Windows принудительно завершит его работу.

Для отладки вашего приложения на предмет обработки завершения работы системы, лучше всего воспользоваться программами для работы с окнами приложений, но только теми, которые умеют отсылать сообщения окнам. Лично мне больше всего понравилась SendMessage.

В приложении пример программы, которая устанавливает строку блокировки и перехватывает завершение работы системы.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

System.Shutdown.Demo.zip (2,614 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 1550 | Комментариев: 0

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2017
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.005 сек.) / Память: 4.5 Mb
Наверх