How to detect a Hung Window ?
http://www.autohotke...p?p=83784#83784
I wanted to write a script that monitors all the visible windows (for responsiveness) and found that a DllCall to "User32.dll\SendMessageTimeout" does the job.
MSDN Reference: SendMessageTimeout Function
LRESULT SendMessageTimeout( HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
UINT fuFlags,
UINT uTimeout,
PDWORD_PTR lpdwResult
);When the above is translated in AHK to our needs, it becomes:DllCall( "SendMessageTimeout" , UInt, ID ; ID will be the handle to the target Window ( ahk_id ) , UInt, 0x00 ; WM_NULL ( the safest message parameter in this case ) , Int , 0 ; wParam - not required , Int , 0 ; lParam - not required , UInt, 0x08 ; SMTO_NOTIMEOUTIFNOTHUNG , Int , 3 ; Timeout in seconds , "UInt *" , Result ) ; Result is the variable that contains the result
I tried different combinations .. The above works well when I wanted to monitor multiple windows.
The difference between SendMessage and PostMessage:
The SendMessage function sends the specified message to a window or windows. The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread’s message queue and returns immediately.
What about SendMessageTimeout?:
The SendMessageTimeout function sends the specified message to a window or windows. The function calls the window procedure for the specified window and, if the specified window belongs to a different thread, does not return until the window procedure has processed the message or the specified time-out period has elapsed. If the window receiving the message belongs to the same queue as the current thread, the window procedure is called directly the time-out value is ignored.
What is the Trick?
When we send a WM_NULL ( 0x00 ) as a message to a window it processes it, and since it has to do nothing returns back the 0x00. However, a "Hung window" will not respond back and so SendMessageTimeout will timeout resulting in a non-zero value in the variable Result.
Any limitations?
A Window might become unresponsive during its startup. SendMessageTimeout (with the example parameters) will see it. This might/might not be the desired effect when monitoring multiple windows. But in case of monitoring a single window, one has the choice to experiment with the fuFlags parameter. There is scope for lot more experimentation with this User32.dll function.
Here is a short version of my script which continuously monitors for window responsiveness (all non-hidden windows).Disclaimer: The below is just an experiment and I have not tested it well! There is an alternative for > Win2000 : user32.dll/IsHungAppWindow - See MSDN Reference : IsHungAppWindow
#Persistent Menu, Tray, Icon, User32.dll, 2 SMTO_NOTIMEOUTIFNOTHUNG := 8 Delay = 200 SetTimer, CheckAllWindows, 10 Return CheckAllWindows: SetTimer, CheckAllWindows, Off WinGet, hWnd, List Loop, %hWnd% { ID := hwnd%A_Index% DllCall("SendMessageTimeout", UInt,ID, UInt, 0, Int,0, Int,0 , UInt, SMTO_NOTIMEOUTIFNOTHUNG, Int,3, "UInt *", Result ) WinGetTitle, Title, ahk_id %ID% IfNotEqual,Result,0, GoSub,Alert Sleep %Delay% } SetTimer, CheckAllWindows, %Delay% Return Alert: ; This routine can be used to repeat testing & offer a WinKill. MsgBox,64,Alert: Window probably hung?!, Window Title: %Title%, 3 Return
So you have copy / pasted the above code and want to test it. Do you have to wait until a Window really hangs?
I ran it from the startup and waited for three days and only today it gave me a notification when an app was opening a huge text file.. ( Ofcourse that was momentary unresponsiveness, but enough proof for me ).
In fact I wanted to post a request in Ask-for-help titled: How to simulate a hung window ?
Lucky I was, to find a simple way: HungGUI.ahk simulates a hung window for testing the above code.. and below is the snapshot of the code :?: HungGUI.ahk plays a foul game by returning -1 for the WM_NULL message it recieves. That does the good for our testing! 8)
Regards,
[How To] detect a Hung Window
It might be of interest that AutoHotkey calls IsHungAppWindow() internally to avoid operating upon hung windows. However, it's not foolproof because sometimes the OS doesn't detect that a window is hung until it's too late and the script has already tried to do something to it (which can cause the script to hang too).
Nice post.
Thanks!
It might be of interest that AutoHotkey calls IsHungAppWindow() internally to avoid operating upon hung windows. However, it's not foolproof because sometimes the OS doesn't detect that a window is hung until it's too late and the script has already tried to do something to it (which can cause the script to hang too).
Oh! When I was tying to simulate a hung window, many times the monitoring script got hung up instead. :shock:
I am still waiting for a real hung window to see whether the monitor is able to see it and WinKill it!
Regards,
CleanNews.in : Bite sized latest news headlines from India with zero bloat
I hope it is useful.
Interesting!
I have tested the script on Win 8.1 and it seems to work.
(I have an application, and if the application is restarted twice, one of them crashes)
But how can I know the PID on the hanging program?
Both have same name in the task manager but different PID.
//Jan
Use the winGet command with the 'list' parameter. This will give you the Hwnd of each of these windows. You can then use these Hwnds and the winGet command (with the 'PID' parameter) to get the PIDs for each instance of the application..
SetTitleMatchMode, 2 WinGet, ID, ID, Google MsgBox, % IsHungAppWindow(ID) IsHungAppWindow(hwnd) { ; 0 - normally, 1 - on the contrary return DllCall("user32\IsHungAppWindow", "Ptr", hwnd) }