Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[How To] detect a Hung Window


  • Please log in to reply
10 replies to this topic
SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

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 ? :D

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 :?: Posted ImageHungGUI.ahk plays a foul game by returning -1 for the WM_NULL message it recieves. That does the good for our testing! 8)

Regards, :)


kWo4Lk1.png

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Nice post.

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).

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

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: :D

I am still waiting for a real hung window to see whether the monitor is able to see it and WinKill it!

Regards, :)
kWo4Lk1.png

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
thanks Suresh! i can already think of a couple of uses for this! :)

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


edwardadams
  • Members
  • 1 posts
  • Last active: May 30 2012 11:05 AM
  • Joined: 30 May 2012
Thanks for your posting, it is very much helpful. =) Try also to follow this link..<!-- m -->http://blogs.msdn.co... ... art-2.aspx<!-- m -->
I hope it is useful.

  • Guests
  • Last active:
  • Joined: --
Can this method be extended to detect a hung process?

Albireo
  • Members
  • 558 posts
  • Last active: Dec 13 2019 02:02 PM
  • Joined: 01 Feb 2006

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



RHCP
  • Members
  • 1228 posts
  • Last active: Apr 08 2017 06:17 PM
  • Joined: 29 May 2006

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..



AHK_Scripter
  • Members
  • 3 posts
  • Last active: Nov 17 2014 04:48 PM
  • Joined: 16 Jul 2014
SetTitleMatchMode, 2
WinGet, ID, ID, Google
MsgBox, % IsHungAppWindow(ID)


IsHungAppWindow(hwnd) { ; 0 - normally, 1 - on the contrary
return DllCall("user32\IsHungAppWindow", "Ptr", hwnd)
}


Skrell
  • Members
  • 384 posts
  • Last active: Jul 07 2016 05:03 PM
  • Joined: 23 Aug 2011

This is SO cool!!!!



Bortseb
  • Members
  • 4 posts
  • Last active: Apr 10 2015 04:51 PM
  • Joined: 21 Mar 2014
This script is almost exactly what I have been looking for! I am not an AHK pro, so hopefully I can get some help with how to tweak this script to get the result I am looking for. I do a lot of CAD work, and big models tend to "hang" (not respond) for quite a while during larger operations. I am frequently waiting for these applications to resume "running" status. Being notified exactly when an application resumes would be really useful to me since I could then go do other work, and not have to spend time checking back in to see if the operation is done. Would there be a simple way to tweak this script so that it alerts me everytime an application switches from a "not responding" state to a "running" state? Running -> Running, and Running -> Not responding, would trigger nothing... only Not Responding -> Running is useful to me