Autohotkey kill hung process

1.9k views Asked by At

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?

1

There are 1 answers

0
Robert Ilbrink On

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:

1. HSHELL_WINDOWCREATED
2. HSHELL_WINDOWDESTROYED
3. HSHELL_ACTIVATESHELLWINDOW
4. HSHELL_WINDOWACTIVATED
5. HSHELL_GETMINRECT
6. HSHELL_REDRAW
7. HSHELL_TASKMAN
8. HSHELL_LANGUAGE
9. HSHELL_SYSMENU
10. HSHELL_ENDTASK
11. HSHELL_ACCESSIBILITYSTATE
12. HSHELL_APPCOMMAND
13. HSHELL_WINDOWREPLACED
14. HSHELL_WINDOWREPLACING
15. HSHELL_HIGHBIT
16. HSHELL_FLASH
17. HSHELL_RUDEAPPACTIVATED

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

 Loop, 25 
   IfLessOrEqual, A_Index, % Round(Volume/4), GuiControl, Show, Text%A_Index%
   Else                                       GuiControl, Hide, Text%A_Index%

 IfEqual, Mute, On, GuiControl, Hide, Icon2
 Else               GuiControl, Show, Icon2

 SetTimer, GuiEscape, 1234
                            }                                      }

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

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 "nn" 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 "nnhWndt: " WinExist("ahk_id" mVal) "nTitlet: " Title "nClass`t: " Class

Return

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% } }