Проверка и обнаружение зависших приложений
Иногда для работы требуется определение зависших приложений, окна которых не отвечают на сообщения. Для этого есть два способа. Первый - официально документированный, через функцию SendMessageTimeOut. Особенность ее работы заключается в том, что после отправки сообщения окну она ждет ответ заданное время, и, если ответа от приложения не последовало, то возвращает FALSE. Вот пример использования функции. Нужные константы, как обычно, в FASM не определены, пришлось брать их из других источников.Code (Assembler) : Убрать нумерацию
- ...
- ; Определить таймаут 50 миллисекунд
- TIMEOUT = 50
- ; Определить константу SMTO_ABORTIFHUNG
- SMTO_ABORTIFHUNG = 2
- ; hwnd - хэндл проверяемого окна
- invoke SendMessageTimeout,[hwnd],NULL,0,0,SMTO_ABORTIFHUNG,TIMEOUT,NULL
- ; Если вернулся 0, то приложение "висит"
- or eax,eax
- jz app_hung_up
- ...
Второй способ - недокументированный. В Windows есть особые функции, которые используются, например, во встроенном Диспетчере задач. Для операционных систем Windows 2000 и выше это IsHungAppWindow, а для систем Windows 9x и Windows ME - функция IsHungThread (она вообще никак не документирована на MSDN). Разница между ними в том, что IsHungAppWindow работает с хэндлом окна, а IsHungThread с хэндлом потока окна. Поскольку в системной библиотеке user32.dll одновменно может быть только одна из этих функций, то включать их в секцию импорта нельзя, иначе ваше приложение вылетит с ошибкой. Также есть информация, что они вообще недоступны через экспорт. Стало быть воспользуемся штатными функциями API GetModuleHandle и GetProcAddress, но предварительно в секции данных определим нужные нам переменные:
Code (Assembler) : Убрать нумерацию
- section '.data' data readable writeable
- ...
- hUser dd ? ; Хэндл библиотеки user32.dll
- hIHW dd ? ; Адрес функции IsHungAppWindow (Win2k и выше)
- hIHT dd ? ; Адрес функции IsHungThread (Win9x)
- strUser db 'user32.dll',0
- strIHW db 'IsHungAppWindow',0
- strIHT db 'IsHungThread',0
- ...
Code (Assembler) : Убрать нумерацию
- section '.code' code readable executable
- ...
- mov [hIHW],0 ; Инициализировать переменные
- mov [hIHT],0
- ; Получить хэндл библиотеки user32.dll
- invoke GetModuleHandle,strUser
- mov [hUser],eax
- chk_WinNT:
- ; Попытаться получить адрес функции IsHungAppWindow
- invoke GetProcAddress,[hUser],strIHW
- or eax,eax
- jz chk_Win9X
- mov [hIHW],eax ; Сохранить адрес функции
- jmp @f
- chk_Win9X:
- ; Попытаться получить адрес функции IsHungThread
- invoke GetProcAddress,[hUser],strIHT
- or eax,eax
- jz loc_fatal_error
- mov [hIHT],eax ; Сохранить адрес функции
- jmp @f
- loc_fatal_error:
- ; По какой-то немыслимой причине не найдено ни одной функции
- ...
- @@:
- ; Продолжить обработку
- ...
Code (Assembler) : Убрать нумерацию
- ;----------------------------------------------------------------
- ; Процедура проверки окна на зависание его родительского приложения
- ; Предварительно должны быть определены переменные hIHW или hIHT
- ; с адресами функций IsHungAppWindow или IsHungThread
- ;
- ; На входе:
- ; hwnd - хэндл проверяемого окна
- ; На выходе:
- ; EAX = 0 - приложение работает или такое окно не найдено
- ; EAX = 1 - приложение зависло и не отвечает
- ;----------------------------------------------------------------
- proc IsAppHung hwnd:dword
- local tmp:DWORD ; Временная переменная
- pusha
- ; Такое окно есть?
- invoke IsWindow,[hwnd]
- or eax,eax
- jz .loc_ret
- .chk_WinNT:
- ; Адрес функции IsHungAppWindow известен?
- cmp [hIHW],0
- je .chk_Win9x
- stdcall [hIHW],[hwnd]
- jmp .loc_ret
- .chk_Win9x:
- ; Адрес функции IsHungThread известен?
- cmp [hIHT],0
- je .chk_All
- invoke GetWindowThreadProcessId,[hwnd],NULL
- stdcall [hIHT],eax
- jmp .loc_ret
- .chk_All:
- ; Определить таймаут 50 миллисекунд
- TIMEOUT = 50
- ; Определить константу SMTO_ABORTIFHUNG
- SMTO_ABORTIFHUNG = 2
- invoke SendMessageTimeout,[hwnd],NULL,0,0,SMTO_ABORTIFHUNG,TIMEOUT,NULL
- sub eax,1
- neg eax
- .loc_ret:
- ; Сохранить значение
- mov [tmp],eax
- ; Восстановить регистры и сохраненное значение
- popa
- mov eax,[tmp]
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;----------------------------------------------------------------
- ; Процедура проверки окна на зависание его родительского приложения
- ;
- ; На входе:
- ; hwnd - хэндл проверяемого окна
- ; На выходе:
- ; EAX = 0 - приложение работает или такое окно не найдено
- ; EAX = 1 - приложение зависло и не отвечает
- ;----------------------------------------------------------------
- proc IsAppHung hwnd:dword
- local tmp:DWORD ; Временная переменная
- pusha
- ; Такое окно есть?
- invoke IsWindow,[hwnd]
- or eax,eax
- jz .loc_ret
- ; Получить хэндл библиотеки user32.dll
- invoke GetModuleHandle,strUser
- mov [tmp],eax
- .chk_WinNT:
- invoke GetProcAddress,[tmp],strIHW
- or eax,eax
- jz .chk_Win9x
- stdcall eax,[hwnd]
- jmp .loc_ret
- .chk_Win9x:
- invoke GetProcAddress,[tmp],strIHT
- or eax,eax
- jz .chk_All
- mov [tmp],eax
- invoke GetWindowThreadProcessId,[hwnd],NULL
- stdcall [tmp],eax
- jmp .loc_ret
- .chk_All:
- ; Определить таймаут 50 миллисекунд
- TIMEOUT = 50
- ; Определить константу SMTO_ABORTIFHUNG
- SMTO_ABORTIFHUNG = 2
- invoke SendMessageTimeout,[hwnd],NULL,0,0,SMTO_ABORTIFHUNG,TIMEOUT,NULL
- sub eax,1
- neg eax
- .loc_ret:
- ; Сохранить значение
- mov [tmp],eax
- ; Восстановить регистры и сохраненное значение
- popa
- mov eax,[tmp]
- ret
- strUser db 'user32.dll',0
- strIHW db 'IsHungAppWindow',0
- strIHT db 'IsHungThread',0
- endp
Для имитации зависшего приложения можно воспользоваться программой Bad Application или программой hangup.exe из архива. В архиве примеры программ для обнаружения зависших приложений всеми тремя способами и программа-имитатор зависшего приложения. Имитаторы зависших приложений придется снимать только через менеджер процессов.
Просмотров: 8310 | Комментариев: 2
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Shukuchi
(09.11.2009 в 03:36):
Рад что наткнулся на ваш блог - кладезь интересной, ценной и такой редкой!!! в наши дни информации. Fasm лучший! ;) Спасибо за ваш труд!)
P.S. сорри за оффтоп.
P.S. сорри за оффтоп.
Добавить комментарий
Заполните форму для добавления комментария
популяризацию и снятия забрала таинственности с тёмных сил.