1

我发现了一种查找挂起进程的方法,但无论我使用什么方法,我似乎都无法杀死它:

    #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

现在,程序发现进程挂起并运行文件,但不会关闭。我也尝试过 WinClose - 没有运气。想法?

4

1 回答 1

1

Feren6,我希望我没有压倒你,但是我曾经剪辑过这段文字,我还没有使用它,希望它可以帮助你,特别是HSHELL_ENDTASK。

wParam 的记录值为:

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 的类型根据接收到的 wParam 的值而有所不同。对于大多数 wParam 值,lParam 是一个窗口句柄,可以在 AHK 的 Window 命令中用作 ahk_id %lParam%。

一些想法:每当窗口被最小化/最大化时,shell 都会接收 HSHELL_GETMINRECT(带有 shellhook 结构)。脚本可能会监视它以将窗口最小化到托盘。当窗口被重绘时,shell 接收 HSHELL_REDRAW。脚本可以监视它以在其内容更改时激活窗口。

我试过试验,这里有一些例子:

实验一:

在 Windows XP 中,CTRL+ALT+DEL 会带来任务管理器。论坛已经看到一些帖子请求拒绝访问任务管理器的方法。以下脚本在创建时几乎立即检测并关闭 Windows 任务管理器。

代码:

执着的

SetBatchLines,-1 进程,优先级,,高

Gui +LastFound hWnd := WinExist()

DllCall("RegisterShellHookWindow", UInt,hWnd) MsgNum := DllCall("RegisterWindowMessage", Str,"SHELLHOOK") OnMessage(MsgNum, "ShellMessage") 返回

ShellMessage(wParam,lParam){如果(wParam = 1);HSHELL_WINDOWCREATED := 1 { WinGetTitle, Title, ahk_id %lParam% If ( Title = "Windows Task Manager" ) { WinClose, ahk_id %lParam% ; 运行,Calc.exe;反而 } } }

实验二:

Hooking Shell 消息提供了一种可靠的方法来跟踪上一个活动窗口。请参阅:如何检索最后一个活动窗口?by r0lZ 以下脚本切换活动窗口的 TopMost/TopLevel 样式(始终在顶部开/关)。

代码:

执着的

菜单,托盘,NoStandard Menu,托盘,添加,切换 AOT,切换 AOT 菜单,托盘,添加,菜单,托盘,添加,重新加载,ExitScript 菜单,托盘,添加,退出,ExitScript 菜单,托盘,提示,切换 AOT 菜单,托盘, 默认, 切换 AOT

Gui +LastFound DllCall( "RegisterShellHookWindow", UInt,WinExist() ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" ) LastActiveWindowID := WinActive("A")

返回 ; // 自动执行部分结束 //

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% 返回

ExitScript: DllCall("DeregisterShellHookWindow", UInt,hWnd) ; 冗余,我猜!IfEqual, A_ThisMenuItem, Reload, Reload ExitApp 返回

运行脚本。单击目标窗口以将其聚焦。双击脚本托盘图标。目标窗口将在 TopMost 和 TopLevel 样式之间切换。

实验三:

我有一个罗技多媒体键盘,但没有安装它附带的软件。我正在使用我自己的 OSD 脚本,它使用 VOLUME_UP /DN/MUTE 键作为热键来触发使用 SoundGet / SoundSet 命令进行调整。

现在我发现,每当我按下多媒体键时,Shell 都会收到通知( HSHELL_APPCOMMAND )。lParam 的 HiWord 包含按下的 MM 键的值。所以我改变了我的音量更改 OSD 脚本,使其在没有 HotKeys 或 SoundSet 命令的情况下工作。

代码: 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 隐藏边框 vText% A_Index% 0x4 ;

返回 ; // 自动执行部分结束 //

ShellMessage( wParam,lParam ) { If ( wParam = 12 AND ( (lParam>>16) >= 8 OR (lParam>>16) <= 10) ) { Gui, Show SoundGet, Volume, MASTER, VOLUME SoundGet, 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

简单地说,当 wParam 为 12 ( HSHELL_APPCOMMAND ) 时, lParam 的 HiWord 包含以下常量之一:

* 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

实验四:

在尝试研究和理解消息时,我编写了这个粗略的 Shell spy 来监视 Shell 接收到的消息:

代码:

执着的

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 ) 返回45) 返回45) 返回

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_LoopF​​ield }

GetAppCommand(FieldN=0) { Global AppCommands Loop, Parse, AppCommands, `n IfEqual, A_Index, %FieldN%, Return, A_LoopF​​ield }

未知: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 " nnhWnd t: " WinExist("ahk_id" mVal) "nTitle t: " Title "nClass`t:" 类

返回

HSHELL_GETMINRECT:返回

HSHELL_APPCOMMAND: GuiControlGet, Msgs GuiControl,, Msgs, % Msgs " // " GetAppCommand( mVal >> 16 ) 返回

GuiClose: Gui, Show, Hide Return

GuiShow: Gui, Show, Return

它并不详尽,但有助于理解这些东西是如何工作的。

运行上述代码后,运行计算器并将其从标准模式更改为科学模式。会发现计算器窗口被破坏并重新创建导致句柄发生变化。( 我不知道 )

有趣的是,我发现每当窗口闪烁其标题栏/任务栏按钮时,Shell 都会收到一个未记录的 (AFAIK) 值 0x8006 ( 32774 )。以下代码激活了一个正在闪烁的窗口:(不确定它是否适用于所有人):

代码: Gui +LastFound

hWnd := WinExist() , DllCall( "RegisterShellHookWindow", UInt,hWnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" )

返回 ; // 自动执行部分结束 //

ShellMessage(wParam,lParam){如果(wParam=0x8006);0x8006 是 32774,如 Spy! { WinActivate, ahk_id %lParam% } }

于 2012-05-24T12:48:43.353 回答