#NoEnv
#SingleInstance Force
SetBatchLines, -1
Process, Priority,, High
SetWorkingDir %A_ScriptDir%
;=======================================活动窗口监控===============================================
RunAsAdmin()
Gui +LastFound
DllCall( "RegisterShellHookWindow", UInt,WinExist() )
OnMessage( DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ), "ShellIMEMessage")
;================================重复进程检查与处理================================================
If A_IsCompiled {
thisPID := DllCall("GetCurrentProcessId")
if objCount(Processlist:=GetProcessNameList(A_ScriptName))>1
{
loop,% objCount(Processlist)
{
if (thisPID<>Processlist[A_Index,2]){
process,Close,% Processlist[A_Index,2]
}
}
}
}Else{
DetectHiddenWindows, On
thisPID := DllCall("GetCurrentProcessId")
WinGet, List, List,%A_ScriptName%
Loop % List
{
WinGet, PID, PID, % "ahk_id " List%A_Index%
;;WinGet, ProcessPath, ProcessPath,% "ahk_id " List%A_Index%
WinGetTitle, WinTitle , % "ahk_id " List%A_Index%
If (PID != thisPID&&WinTitle=A_ScriptName){
process,Close,% PID
}
}
DetectHiddenWindows, Off
}
;;刷新任务栏残留的图标残影
TrayRefresh()
Return
;;================================监控消息回调ShellIMEMessage监控窗口变化================================
ShellIMEMessage( wParam,lParam ) {
/* wParam参数:
;1 顶级窗体被创建 ;2 顶级窗体即将被关闭 ;54 退出全屏 ;32772 窗口切换
;3 SHELL 的主窗体将被激活 ;4 顶级窗体被激活 ;&H8000& 掩码 ;53 全屏
;5 顶级窗体被最大化或最小化 ;6 Windows 任务栏被刷新,也可以理解成标题变更
;7 任务列表的内容被选中 ;8 中英文切换或输入法切换 ;13 wParam=被替换的顶级窗口的hWnd
;9 显示系统菜单 ;10 顶级窗体被强制关闭 ;14 wParam=替换顶级窗口的窗口hWnd
;12 没有被程序处理的APPCOMMAND。见WM_APPCOMMAND
*/
WinWait , %A_ScriptName%, , 1
;消除重复运行程序时弹出”Could not close the previous instance of this script. Keep waiting“窗口
ControlGetText, WinStaticText , Static1,ahk_class #32770
if WinExist(A_ScriptName)&&InStr(WinStaticText,"keep Waiting"){ ;ahk_class #32770
DllCall("DestroyWindow", "ptr", WinExist(A_ScriptName))
Reload
}
}
;;根据进程文件名获取进程信息列表
GetProcessNameList(ProcessName:=""){
list:="",tarr:=[]
s := 10240 ; 缓存和数组的大小(4 KB)
Process, Exist ; 设置 ErrorLevel 为这个正在运行脚本的 PID.
; 使用 PROCESS_QUERY_INFORMATION(0x0400) 获取此脚本的句柄:
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel, "Ptr")
; 打开此进程的可调整的访问令牌(TOKEN_ADJUST_PRIVILEGES = 32):
DllCall("Advapi32.dll\OpenProcessToken", "Ptr", h, "UInt", 32, "PtrP", t)
VarSetCapacity(ti, 16, 0) ; 特权结构
NumPut(1, ti, 0, "UInt") ; 特权数组中的一个条目...
; 获取调试特权的本地唯一标识符:
DllCall("Advapi32.dll\LookupPrivilegeValue", "Ptr", 0, "Str", "SeDebugPrivilege", "Int64P", luid)
NumPut(luid, ti, 4, "Int64")
NumPut(2, ti, 12, "UInt") ; 启用这个特权: SE_PRIVILEGE_ENABLED = 2
; 使用新的访问令牌更新此进程的特权:
r := DllCall("Advapi32.dll\AdjustTokenPrivileges", "Ptr", t, "Int", false, "Ptr", &ti, "UInt", 0, "Ptr", 0, "Ptr", 0)
DllCall("CloseHandle", "Ptr", t) ; 关闭此访问令牌句柄以节约内存.
DllCall("CloseHandle", "Ptr", h) ; 关闭此进程句柄以节约内存.
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll") ; 通过预加载来提升性能.
s := VarSetCapacity(a, s) ; 接收进程列表标识符的数组:
DllCall("Psapi.dll\EnumProcesses", "Ptr", &a, "UInt", s, "UIntP", r)
Loop, % r // 4 ; 把数组解析为 DWORD(32 位) 的标识符:
{
id := NumGet(a, A_Index * 4, "UInt")
; 打开进程: PROCESS_VM_READ(0x0010) | PROCESS_QUERY_INFORMATION(0x0400)
h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id, "Ptr")
if !h
continue
VarSetCapacity(n, s, 0) ; 接收模块基础名称的缓存:
e := DllCall("Psapi.dll\GetModuleBaseName", "Ptr", h, "Ptr", 0, "Str", n, "UInt", A_IsUnicode ? s//2 : s)
if !e ; 用于 64 位进程在 32 位模式时的回退方法:
if e := DllCall("Psapi.dll\GetProcessImageFileName", "Ptr", h, "Str", n, "UInt", A_IsUnicode ? s//2 : s)
SplitPath n, n
DllCall("CloseHandle", "Ptr", h) ; 关闭进程句柄以节约内存
if (n && e){ ; 如果映像不是空的, 则添加到列表:
If (ProcessName&&ProcessName=n)
tarr.push([n,id])
else
list.=n "/" id "|"
}
}
DllCall("FreeLibrary", "Ptr", hModule) ; 卸载库来释放内存.
return !ProcessName?list:tarr
}
TrayRefresh() {
/* Remove any dead icon from the tray menu
* Should work both for W7 & W10
*/
WM_MOUSEMOVE := 0x200
detectHiddenWin := A_DetectHiddenWindows
DetectHiddenWindows, On
allTitles := ["ahk_class Shell_TrayWnd"
, "ahk_class NotifyIconOverflowWindow"]
allControls := ["ToolbarWindow321"
,"ToolbarWindow322"
,"ToolbarWindow323"
,"ToolbarWindow324"]
allIconSizes := [24,32]
for id, title in allTitles {
for id, controlName in allControls
{
for id, iconSize in allIconSizes
{
ControlGetPos, xTray,yTray,wdTray,htTray,% controlName,% title
y := htTray - 10
While (y > 0)
{
x := wdTray - iconSize/2
While (x > 0)
{
point := (y << 16) + x
PostMessage,% WM_MOUSEMOVE, 0,% point,% controlName,% title
x -= iconSize/2
}
y -= iconSize/2
}
}
}
}
DetectHiddenWindows, %detectHiddenWin%
}
RunAsAdmin(){
full_command_line := DllCall("GetCommandLine", "str")
if not (A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)")) {
try {
if A_IsCompiled
Run *RunAs "%A_ScriptFullPath%" /restart
else
Run *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%"
}Catch e{
MsgBox, 262160,Error,% e.Extra?e.Extra:"以管理员身份运行失败!",15
ExitApp
}
}
}
辛苦