Як визначити, що програма не відповідає
Колись, за часів Windows 3.1, усі програми мали одну загальну чергу подій введення. Якщо одна з програм з якихось причин переставала обробляти повідомлення, це могло призвести до зависання всієї системи. Часи змінилися, і тепер, у 32-бітній та багатопотоковій Windows, кожен потік має свою чергу введення. Однак зависаючі програми не зникли. Як відрізнити програми, які сумлінно обробляють повідомлення від тих, що перестали реагувати на запити користувача, ми обговоримо в цій статті.
Ми розглянемо два способи вирішення цього завдання. Один з них, з використанням функції SendMessageTimeout, - той, який Microsoft рекомендує у своїй базі знань. Інший - той, який насправді використовують програми Microsoft. В обох випадках функція для визначення завислих додатків матиме наступний прототип:
Тут hWnd - ідентифікатор головного вікна програми, а pbHung - покажчик на змінну типу BOOL, яку функція встановлює в TRUE, якщо програма дійсно не відповідає.
Використання функції SendMessageTimeout
Функція SendMessageTimeout надсилає повідомлення вказаному вікну. Функція примітна тим, що у випадку, якщо вікно належить іншому потоку, вона не повертає керування доти, доки вікно не обробить повідомлення, або закінчиться вказаний інтервал часу. Крім того, якщо вказаний прапор SMTO_ABORTIFHUNG, і схоже, що програма зависла, функція повертає управління відразу ж, не чекаючи, коли закінчиться тайм. Саме ця властивість SendMessageTimeout дозволяє використовувати її для визначення завислих додатків.
Ми надсилаємо повідомлення WM_NULL головному вікну програми, що перевіряється. Якщо це повідомлення будеуспішно доставлено вікно, то вікно його просто проігнорує, якщо ж SendMessageTimeout поверне помилку, ми вважаємо, що програма зависла.
Використання недокументованих функцій IsHungAppWindow та IsHungThread
Як зазначалося, програми Microsoft, зокрема Windows NT Task Manager і Windows 95 Task List не використовують SendMessageTimeout визначення зависших додатків. Натомість вони користуються двома недокументованими функціями.
У Windows NT/2000 бібліотека USER32.DLL експортує функцію IsHungAppWindow, прототип якої наведено нижче. Task Manager використовує цю функцію, щоб знайти програми, які перестали відповідати на повідомлення.
У Windows 9x/Me USER32.DLL експортує аналогічну функцію під назвою IsHungThread, яка відрізняється від свого NT-собрата тим, що приймає не ідентифікатор вікна, а ідентифікатор потоку.
Озброєні цими знаннями, ми можемо написати іншу функцію для визначення додатків, що зависли:
Нова функція починає працювати з визначення версії Windows. Якщо програма виконується на Windows NT, вона знаходить і викликає функцію IsHungAppWindow . При роботі на Windows 9x, функція спочатку визначає ідентифікатор потоку, якому належить вказане вікно, а потім викликає IsHungThread. Все дуже просто.
Висновок
Таким чином, ми розглянули два способи визначення додатків, які перестали відповідати на запити користувачів. У процесі тестування я виявив, що функція SendMessageTimeout для нової програми повертає управління з невеликою затримкою, хоча і повідомляє про те, що програма зависла. Через деякий час, коли система переконується, що програма дійсно зависла, вона починає повертати управліннявідразу. IsHungAppWindow та IsHungThread не мають цього недоліку.
Щоб перевірити описані в цій статті функції, можна скористатися тестовим додатком Process Viewer. Як зависну програму можна використовувати невелику програму HUNGTEST, яка також додається до цієї статті.