检测在运行的脚本
获取系统中当前运行的所有 AutoHotkey 脚本的信息(下面的脚本获取脚本标题和进程路径):
Code: Select all
DetectHiddenWindows, on
WinGet, AHKWinList, List, ahk_class AutoHotkey
Loop, %AHKWinList%
{
AHKWinHWND := AHKWinList%A_Index%
WinGetTitle, AHKWinTitle, ahk_id %AHKWinHWND%
WinGet, AHKWinProcessPath, ProcessPath, ahk_id %AHKWinHWND%
MsgBox, % "脚本标题:" AHKWinTitle "`n脚本进程路径:" AHKWinProcessPath
}
return
D:\Software\AutoHotkey\Scripts\test.ahk - AutoHotkey v1.1.15.00
当然,还可以使用其他方法。下面通过消息获取某脚本的进程 ID:
Code: Select all
AHKScriptName := "MyScript.ahk"
SetTitleMatchMode, 2
DetectHiddenWindows, on
SendMessage, 0x44, 0x405, 0, , %AHKScriptName% ahk_class AutoHotkey
MsgBox %ErrorLevel% is the process id.
- D:\Software\AutoHotkey\Scripts\test.ahk - AutoHotkey v1.1.15.00
- D:\Software\AutoHotkey\Scripts\test.exe
对这些脚本进行控制
在写脚本时,我们都知道可以很方便的对当前脚本进行控制,如:
Code: Select all
Pause::Pause
^!s::Suspend
^!r::Reload
^+q::ExitApp
!l::ListLines
!v::ListVars
!k::KeyHistory
Code: Select all
AHKScriptName := "MyScript.ahk"
DetectHiddenWindows On ; 才可以检测到脚本的隐藏主窗口.
SetTitleMatchMode 2 ; 避免为下面的文件指定完整的路径.
WM_COMMAND := 0x111
ID_FILE_PAUSE := 65403
ID_FILE_SUSPEND := 65404
PostMessage, %WM_COMMAND%, %ID_FILE_PAUSE%,,, %AHKScriptName% ahk_class AutoHotkey
PostMessage, %WM_COMMAND%, %ID_FILE_SUSPEND%,,, %AHKScriptName% ahk_class AutoHotkey
WinClose, %AHKScriptName% ahk_class AutoHotkey ; 关闭脚本,也可以使用消息,不过这里使用窗口命令可能直观一些。
; 下面两个同样是挂起和暂停的功能
PostMessage, 0x111, 65305,,, %AHKScriptName% ahk_class AutoHotkey ; 挂起
PostMessage, 0x111, 65306,,, %AHKScriptName% ahk_class AutoHotkey ; 暂停
还有哪些可用的消息?我提供几点思路供参考:
- 执行操作时通过工具截取消息(消息很多,这些属于 WM_COMMAND)
- 直接到官方论坛询问作者
0: unused (possibly special in some contexts)
1: IDOK
2: IDCANCEL
3 to 1002: GUI window control IDs (these IDs must be unique only within their parent, not across all GUI windows)
1003 to 65299: User Defined Menu IDs
65300 to 65399: Standard tray menu items.
65400 to 65534: main menu items
消息号| 含义1: IDOK
2: IDCANCEL
3 to 1002: GUI window control IDs (these IDs must be unique only within their parent, not across all GUI windows)
1003 to 65299: User Defined Menu IDs
65300 to 65399: Standard tray menu items.
65400 to 65534: main menu items
----- | -----
65300 | ID_TRAY_OPEN
65400 | ID_FILE_RELOADSCRIPT, ID_TRAY_RELOADSCRIPT
65401 | ID_FILE_EDITSCRIPT, ID_TRAY_EDITSCRIPT
65402 | ID_FILE_WINDOWSPY, ID_TRAY_WINDOWSPY
65403 | ID_FILE_PAUSE, ID_TRAY_PAUSE
65404 | ID_FILE_SUSPEND, ID_TRAY_SUSPEND
65405 | ID_FILE_EXIT, ID_TRAY_EXIT
65406 | ID_VIEW_LINES
65407 | ID_VIEW_VARIABLES
65408 | ID_VIEW_HOTKEYS
65409 | ID_VIEW_KEYHISTORY
65410 | ID_VIEW_REFRESH
65411 | ID_HELP_USERMANUAL, ID_TRAY_HELP
65412 | ID_HELP_WEBSITE
注:一般而言在更新版本时消息号的用途不太可能发生变化,不过为了安全,在使用前最好明确其用途,否则可能发生意外情况。
实现的具体原理
在前面的脚本中我们应该注意到两点:
- 开启了对隐藏窗口的检测
- 使用 AutoHotkey 类名获取窗口
说到这里,我想起了一个有趣的事情:为什么 AutoHotkey 被称为模拟多线程呢?从这里可以判断出,每个脚本运行时至少有两个线程:
- 主线程,运行主窗口,负责接受消息、缓冲热键及伪线程的中断和切换等
这里的描述可能不太准确和全面,不过大体上可以这么理解,其中的伪线程是指帮助中所说的线程概念(例如 Thread 中所描述的线程,注意帮助中除了 A_ScriptHwnd 外从未涉及到主线程)。 - 脚本线程,实际执行脚本的线程,这不用多说了,它执行的就是我们写的脚本。
小结
尽管未谈到游戏,不过主要内容前面都说完了。因此,要检测 AutoHotkey 脚本的外挂只需在脚本启动及运行时定期执行:
Code: Select all
DetectHiddenWindows, on
While WinExist("ahk_class AutoHotkey")
WinKill