Author: Ido Kanner
In many situations you might like to detect if an application is blocked. For
example while automating Word, you'd like to know if Word has stopped responding.
This article describes how to detect if an application has stopped responding using
some undocumented functions.
Answer:
1 {2 // (c)1999 Ashot Oganesyan K, SmartLine, Inc3 // mailto:ashot@aha.ru, http://www.protect-me.com, http://www.codepile.com4 5 The code doesn't use the Win32 API SendMessageTimout function to6 determine if the target application is responding but calls7 undocumented functions from the User32.dll.8 9 --> For Windows 95/98/ME we call the IsHungThread() API10 11 The function IsHungAppWindow retrieves the status (running or not responding)12 of the specified application13 14 IsHungAppWindow(Wnd: HWND): // handle to main app's window15 BOOL;16 17 --> For NT/2000/XP the IsHungAppWindow() API:18 19 The function IsHungThread retrieves the status (running or not responding) of20 the specified thread21 22 IsHungThread(DWORD dwThreadId): // The thread's identifier of the main app's window23 BOOL;24 25 Unfortunately, Microsoft doesn't provide us with the exports symbols in the26 User32.lib for these functions, so we should load them dynamically using the 27 GetModuleHandle and28 GetProcAddress functions:29 }30 31 // For Win9x/ME32 33 function IsAppRespondig9x(dwThreadId: DWORD): Boolean;
34 type35 TIsHungThread = function(dwThreadId: DWORD): BOOL; stdcall;
36 var37 hUser32: THandle;
38 IsHungThread: TIsHungThread;
39 begin40 Result := True;
41 hUser32 := GetModuleHandle('user32.dll');
42 if (hUser32 > 0) then43 begin44 @IsHungThread := GetProcAddress(hUser32, 'IsHungThread');
45 if Assigned(IsHungThread) then46 begin47 Result := not IsHungThread(dwThreadId);
48 end;
49 end;
50 end;
51 52 // For Win NT/2000/XP53 54 function IsAppRespondigNT(wnd: HWND): Boolean;
55 type56 TIsHungAppWindow = function(wnd: hWnd): BOOL; stdcall;
57 var58 hUser32: THandle;
59 IsHungAppWindow: TIsHungAppWindow;
60 begin61 Result := True;
62 hUser32 := GetModuleHandle('user32.dll');
63 if (hKernel > 0) then64 begin65 @IsHungAppWindow := GetProcAddress(hUser32, 'IsHungAppWindow');
66 if Assigned(IsHungAppWindow) then67 begin68 Result := not IsHungAppWindow(wnd);
69 end;
70 end;
71 end;
72 73 function IsAppRespondig(Wnd: HWND): Boolean;
74 begin75 ifnot IsWindow(Wnd) then76 begin77 ShowMessage('Incorrect window handle');
78 Exit;
79 end;
80 if Win32Platform = VER_PLATFORM_WIN32_NT then81 Result := IsAppRespondigNT(wnd)
82 else83 Result := IsAppRespondig9X(GetWindowThreadProcessId(wnd, nil));
84 end;
85 86 // Example: Check if Word is hung/responing87 88 procedure TForm1.Button3Click(Sender: TObject);
89 var90 Res: DWORD;
91 h: HWND;
92 begin93 // Find Word by classname94 h := FindWindow(PChar('OpusApp'), nil);
95 if h <> 0 then96 begin97 if IsAppRespondig(h) then98 ShowMessage('Word is responding')
99 else100 ShowMessage('Word is not responding');
101 end102 else103 ShowMessage('Word is not open');
104 end;