I discovered a way to find a hung process, but no matter what method I use I can't seem to kill it:
#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%
PID := DllCall("GetCurrentProcessId")
IfNotEqual,Result,0,GoSub,Alert
Sleep %Delay%
}
SetTimer, CheckAllWindows, %Delay%
Return
Alert: ; This routine can be used to repeat testing & offer a WinKill.
Process, Close, PID
Sleep 50000
Run, "C:\Program Files\sample_file.exe"
Return
Right now, the program discovers that the process is hung and will run the file, but it won't close. I tried WinClose as well -- no luck. Thoughts?
Feren6, I hope I am not overwhelming you, but I once clipped this text and I have not yet used it, I hope it can help you, especially the HSHELL_ENDTASK.
The documented values for wParam are:
lParam differs in type according to the value of wParam received. For most of the wParam values, the lParam is a handle to a window that can be used as ahk_id %lParam% in AHK's Window commands.
Some ideas: The shell receives HSHELL_GETMINRECT ( with a shellhook structure ) whenever a window is being Minimised/Maximised. A script may monitor it to Minimize a window to the tray. The shell receives HSHELL_REDRAW when a window is being Redrawn. A script may monitor it to activate a window whenever its contents are changed.
I tried experimenting and here are some examples:
Experiment 1:
In Windows XP, CTRL+ALT+DEL brings the Task Manager. The forum has seen some posts requesting a way to deny the access to Task Manager. The following scripts detects and closes Windows Task Manager almost instantly when created.
Code:
Persistent
SetBatchLines, -1 Process, Priority,, High
Gui +LastFound hWnd := WinExist()
DllCall( "RegisterShellHookWindow", UInt,hWnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" ) Return
ShellMessage( wParam,lParam ) { If ( wParam = 1 ) ; HSHELL_WINDOWCREATED := 1 { WinGetTitle, Title, ahk_id %lParam% If ( Title = "Windows Task Manager" ) { WinClose, ahk_id %lParam% ; Run, Calc.exe ; instead } } }
Experiment 2:
Hooking Shell messages provides a sure shot way of keeping a track on Last Active Window. See: How to retrieve LAST active window? by r0lZ The following script toggles the TopMost/TopLevel styles ( Always on Top On/OFF ) of the active window.
Code:
Persistent
Menu, Tray, NoStandard Menu, Tray, Add, Toggle AOT, ToggleAOT Menu, Tray, Add, Menu, Tray, Add, Reload, ExitScript Menu, Tray, Add, Exit , ExitScript Menu, Tray, Tip, Toggle AOT Menu, Tray, Default, Toggle AOT
Gui +LastFound DllCall( "RegisterShellHookWindow", UInt,WinExist() ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" ) LastActiveWindowID := WinActive("A")
Return ; // End of Auto-Execute Section //
ShellMessage( wParam, lParam ) { Global LastActiveWindowID If ( wParam = 4 And WinExist( "ahk_id " lParam ) ) { ; HSHELL_WINDOWACTIVATED = 4 LastActiveWindowID := lParam } }
ToggleAOT: WinSet, AlwaysOnTop, Toggle, ahk_id %LastActiveWindowID% Return
ExitScript: DllCall( "DeregisterShellHookWindow", UInt,hWnd ) ; Redundant, I guess! IfEqual, A_ThisMenuItem, Reload, Reload ExitApp Return
Run the script. Click on the target window to focus it. Double click on the scripts tray icon. The target window will be toggled between TopMost and TopLevel styles.
Experiment 3:
I have a Logitech multimedia Keyboard and have not installed the software that came with it. I was using my own OSD script which used VOLUME_UP /DN/MUTE keys as hotkeys to trigger adjustment with SoundGet / SoundSet commands.
Now I have found that, the Shell is notified ( HSHELL_APPCOMMAND ) whenever I press a mulitmedia key. The HiWord of lParam contains the value of the MM key pressed. So I have altered my Volume Change OSD script to work without HotKeys or SoundSet command.
Code: Gui, Color, FFFFFF Gui, -Caption +Border +AlwaysOnTop +ToolWindow +LastFound
hWnd := WinExist() , DllCall( "RegisterShellHookWindow", UInt,hWnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" )
Gui, Add, Picture, x5 y5 w32 h32 Icon4 vIcon1, SndVol32.exe Gui, Add, Picture, x5 y5 w32 h32 Icon5 vIcon2, SndVol32.exe Loop,25 Gui, Add, Text, x+3 w5 h32 Hidden Border vText%A_Index% 0x4 ;
Return ; // End of Auto-Exexute Section //
ShellMessage( wParam,lParam ) { If ( wParam = 12 AND ( (lParam>>16) >= 8 OR (lParam>>16) <= 10) ) { Gui, Show SoundGet, Volume, MASTER, VOLUME SoundGet, Mute , , MUTE
GuiEscape: SetTimer, GuiEscape, OFF Gui, Hide
Simply put, when wParam is 12 ( HSHELL_APPCOMMAND ), the HiWord of lParam contains one of the following constants:
APPCOMMAND_BROWSER_FORWARD = 2 APPCOMMAND_BROWSER_REFRESH = 3 APPCOMMAND_BROWSER_STOP = 4 APPCOMMAND_BROWSER_SEARCH = 5 APPCOMMAND_BROWSER_FAVORITES = 6 APPCOMMAND_BROWSER_HOME = 7 APPCOMMAND_VOLUME_MUTE = 8 APPCOMMAND_VOLUME_DOWN = 9 APPCOMMAND_VOLUME_UP = 10 APPCOMMAND_MEDIA_NEXTTRACK = 11 APPCOMMAND_MEDIA_PREVIOUSTRACK = 12 APPCOMMAND_MEDIA_STOP = 13 APPCOMMAND_MEDIA_PLAY_PAUSE = 14 APPCOMMAND_LAUNCH_MAIL = 15 APPCOMMAND_LAUNCH_MEDIA_SELECT = 16 APPCOMMAND_LAUNCH_APP1 = 17 APPCOMMAND_LAUNCH_APP2 = 18 APPCOMMAND_BASS_DOWN = 19 APPCOMMAND_BASS_BOOST = 20 APPCOMMAND_BASS_UP = 21 APPCOMMAND_TREBLE_DOWN = 22 APPCOMMAND_TREBLE_UP = 23 APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24 APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25 APPCOMMAND_MICROPHONE_VOLUME_UP = 26 APPCOMMAND_HELP = 27 APPCOMMAND_FIND = 28 APPCOMMAND_NEW = 29 APPCOMMAND_OPEN = 30 APPCOMMAND_CLOSE = 31 APPCOMMAND_SAVE = 32 APPCOMMAND_PRINT = 33 APPCOMMAND_UNDO = 34 APPCOMMAND_REDO = 35 APPCOMMAND_COPY = 36 APPCOMMAND_CUT = 37 APPCOMMAND_PASTE = 38 APPCOMMAND_REPLY_TO_MAIL = 39 APPCOMMAND_FORWARD_MAIL = 40 APPCOMMAND_SEND_MAIL = 41 APPCOMMAND_SPELL_CHECK = 42 APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43 APPCOMMAND_MIC_ON_OFF_TOGGLE = 44 APPCOMMAND_CORRECTION_LIST = 45
Experiment 4:
While trying to study and understand the messages I wrote this crude Shell spy to monitor the messages being received by the Shell :
Code:
Persistent
Menu,Tray,Add Menu,Tray,Add, &Show, GuiShow Menu,Tray,Default, &Show Gui, Font, s9, Courier New
Gui +ToolWindow +AlwaysOnTop +Resize +LastFound hWnd := WinExist() DllCall( "RegisterShellHookWindow", UInt,hWnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessages" )
Gui, Add, Edit, w512 h512 vMsgs hwndEditC +ReadOnly Gui, Show, x10 y10, Shell Spy
MsgNames = ( HSHELL_WINDOWCREATED HSHELL_WINDOWDESTROYED HSHELL_ACTIVATESHELLWINDOW HSHELL_WINDOWACTIVATED HSHELL_GETMINRECT HSHELL_REDRAW HSHELL_TASKMAN HSHELL_LANGUAGE HSHELL_SYSMENU HSHELL_ENDTASK HSHELL_ACCESSIBILITYSTATE HSHELL_APPCOMMAND HSHELL_WINDOWREPLACED HSHELL_WINDOWREPLACING HSHELL_HIGHBIT HSHELL_FLASH HSHELL_RUDEAPPACTIVATED )
AppCommands = ( APPCOMMAND_BROWSER_BACKWARD = 1 APPCOMMAND_BROWSER_FORWARD = 2 APPCOMMAND_BROWSER_REFRESH = 3 APPCOMMAND_BROWSER_STOP = 4 APPCOMMAND_BROWSER_SEARCH = 5 APPCOMMAND_BROWSER_FAVORITES = 6 APPCOMMAND_BROWSER_HOME = 7 APPCOMMAND_VOLUME_MUTE = 8 APPCOMMAND_VOLUME_DOWN = 9 APPCOMMAND_VOLUME_UP = 10 APPCOMMAND_MEDIA_NEXTTRACK = 11 APPCOMMAND_MEDIA_PREVIOUSTRACK = 12 APPCOMMAND_MEDIA_STOP = 13 APPCOMMAND_MEDIA_PLAY_PAUSE = 14 APPCOMMAND_LAUNCH_MAIL = 15 APPCOMMAND_LAUNCH_MEDIA_SELECT = 16 APPCOMMAND_LAUNCH_APP1 = 17 APPCOMMAND_LAUNCH_APP2 = 18 APPCOMMAND_BASS_DOWN = 19 APPCOMMAND_BASS_BOOST = 20 APPCOMMAND_BASS_UP = 21 APPCOMMAND_TREBLE_DOWN = 22 APPCOMMAND_TREBLE_UP = 23 APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24 APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25 APPCOMMAND_MICROPHONE_VOLUME_UP = 26 APPCOMMAND_HELP = 27 APPCOMMAND_FIND = 28 APPCOMMAND_NEW = 29 APPCOMMAND_OPEN = 30 APPCOMMAND_CLOSE = 31 APPCOMMAND_SAVE = 32 APPCOMMAND_PRINT = 33 APPCOMMAND_UNDO = 34 APPCOMMAND_REDO = 35 APPCOMMAND_COPY = 36 APPCOMMAND_CUT = 37 APPCOMMAND_PASTE = 38 APPCOMMAND_REPLY_TO_MAIL = 39 APPCOMMAND_FORWARD_MAIL = 40 APPCOMMAND_SEND_MAIL = 41 APPCOMMAND_SPELL_CHECK = 42 APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43 APPCOMMAND_MIC_ON_OFF_TOGGLE = 44 APPCOMMAND_CORRECTION_LIST = 45 ) Return
ShellMessages( wP,lP ) { Global EditC Global mVal := lP GuiControlGet, Msgs Routine := GetMessageName( wP ) IfEqual,Routine,, SetEnv, Routine, UNKNOWN GuiControl,, Msgs, % Msgs "
n
n" Routine " [" wP "]" If IsLabel(Routine) GoSub, %Routine% ControlSend,, ^{End}, ahk_id %EditC% }GetMessageName( FieldN=0 ) { Global MsgNames Loop, Parse, MsgNames, `n IfEqual, A_Index, %FieldN%, Return, A_LoopField }
GetAppCommand( FieldN=0 ) { Global AppCommands Loop, Parse, AppCommands, `n IfEqual, A_Index, %FieldN%, Return, A_LoopField }
UNKNOWN: HSHELL_WINDOWCREATED: HSHELL_WINDOWACTIVATED: HSHELL_WINDOWDESTROYED: HSHELL_REDRAW: HSHELL_FLASH: HSHELL_ENDTASK: HSHELL_WINDOWREPLACING: HSHELL_WINDOWREPLACED:
HSHELL_RUDEAPPACTIVATED:
WinGetTitle, Title, ahk_id %mVal% WinGetClass, Class, ahk_id %mVal% GuiControlGet, Msgs GuiControl,, Msgs , % Msgs "
n
nhWndt: " WinExist("ahk_id" mVal) "
nTitlet: " Title "
nClass`t: " ClassReturn
HSHELL_GETMINRECT: Return
HSHELL_APPCOMMAND: GuiControlGet, Msgs GuiControl,, Msgs, % Msgs " // " GetAppCommand( mVal >> 16 ) Return
GuiClose: Gui, Show, Hide Return
GuiShow: Gui, Show, Return
It is not exhaustive, but useful to understand how the stuff works.
With the above code running, Run Calculator and change it from Standard to Scientific mode. One will find that the Calculator window is destroyed and created again resulting in the change of handle. ( I did not know it )
Interestingly I found that an undocumented ( AFAIK ) value of 0x8006 ( 32774 ) is received by the Shell whenever a Window is Flashing its Titlebar/Taskbar button. The following code activates a window that is flashing: ( not sure whether it will work for everyone ) :
Code: Gui +LastFound
hWnd := WinExist() , DllCall( "RegisterShellHookWindow", UInt,hWnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" )
Return ; // End of Auto-Execute Section //
ShellMessage( wParam,lParam ) { If ( wParam = 0x8006 ) ; 0x8006 is 32774 as shown in Spy! { WinActivate, ahk_id %lParam% } }