Script tested on Windows 10, with all icons visible setting.
Removes an icon by process name from the system tray.
; AutoHotkey v2
; Based on https://www.autohotkey.com/boards/viewtopic.php?p=414590#p414590 "[LIB] TrayIcon - Sean's TrayIcon for Unicode and 64 bit"
TrayIcon_GetTrayBar(sTray := "Shell_TrayWnd") {
idxTB := "", nTB := ""
dhw := A_DetectHiddenWindows
DetectHiddenWindows(1)
for k in WinGetControls("ahk_class " sTray)
if RegExMatch(k, "(?<=ToolbarWindow32)\d+(?!.*ToolbarWindow32)", &nTB)
loop nTB[] {
hWnd := ControlGetHwnd("ToolbarWindow32" A_Index, "ahk_class " sTray)
hParent := DllCall("GetParent", "Ptr",hWnd)
sClass := WinGetClass("ahk_id " hParent)
if not (sClass == "SysPager" or sClass == "NotifyIconOverflowWindow")
continue
idxTB := A_Index
break
}
DetectHiddenWindows(dhw)
return idxTB
}
; sExeName - exe name or empty for all icons
; oTrayInfo - array of objects icons data:
; idx - 0 based tray icon index
; idcmd - Command identifier associated with the button
; pid - Process ID
; uid - Application defined identifier for the icon
; msgid - Application defined callback message
; hicon - Handle to the tray icon
; hwnd - Window handle
; class - Window class
; process - Process executable
; tray - Tray Type (Shell_TrayWnd or NotifyIconOverflowWindow)
; tooltip - Tray icon tooltip
TrayIcon_GetInfo(sExeName := "") {
dhw := A_DetectHiddenWindows
DetectHiddenWindows(1)
oTrayInfo := []
for sTray in ["Shell_TrayWnd", "NotifyIconOverflowWindow"] {
idxTB := TrayIcon_GetTrayBar(sTray)
pidTaskbar := WinGetPID("ahk_class " sTray)
hProc := DllCall("OpenProcess", "UInt",0x38, "Int",0, "UInt",pidTaskbar)
pRB := DllCall("VirtualAllocEx", "Ptr",hProc, "Ptr",0, "UPtr",20, "UInt",0x1000, "UInt",0x04)
btn := Buffer(A_Is64bitOS ? 32 : 20, 0)
nfo := Buffer(A_Is64bitOS ? 32 : 24, 0)
tip := Buffer(128 * 2, 0)
res := SendMessage(TB_BUTTONCOUNT := 0x0418, 0, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
Loop res {
SendMessage(TB_GETBUTTON := 0x0417, A_Index - 1, pRB, "ToolbarWindow32" idxTB, "ahk_class " sTray)
DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",pRB, "Ptr",btn.Ptr, "UPtr",btn.Size, "UPtr",0)
iBitmap := NumGet(btn, 0, "Int")
idCmd := NumGet(btn, 4, "Int")
fsState := NumGet(btn, 8, "UChar")
fsStyle := NumGet(btn, 9, "UChar")
dwData := NumGet(btn, A_Is64bitOS ? 16 : 12, "UPtr")
iString := NumGet(btn, A_Is64bitOS ? 24 : 16, "Ptr")
DllCall("ReadProcessMemory", "Ptr",hProc, "Ptr",dwData, "Ptr",nfo.Ptr, "UPtr",nfo.Size, "UPtr",0)
hWnd := NumGet(nfo, 0, "Ptr")
uId := NumGet(nfo, A_Is64bitOS ? 8 : 4, "UInt")
msgId := NumGet(nfo, A_Is64bitOS ? 12 : 8, "UPtr")
hIcon := NumGet(nfo, A_Is64bitOS ? 24 : 20, "Ptr")
nPid := WinGetPID("ahk_id " hWnd)
sProcess := WinGetProcessName("ahk_id " hWnd)
sClass := WinGetClass("ahk_id " hWnd)
If ( (sExeName = "-" && !sProcess) || (sExeName == "--" && !nPid) || (!sExeName) || (sExeName = sProcess) || (sExeName == nPid))
{
DllCall("ReadProcessMemory" , "Ptr",hProc, "Ptr",iString, "Ptr",tip.Ptr, "UPtr",tip.Size, "UPtr",0)
oTrayInfo.Push(Map( "idx" , A_Index - 1
, "idcmd" , idCmd
, "pid" , nPid
, "uid" , uId
, "msgid" , msgId
, "hicon" , hIcon
, "hwnd" , hWnd
, "class" , sClass
, "process" , sProcess
, "tooltip" , StrGet(tip.Ptr, "UTF-16")
, "tray" , sTray))
}
}
DllCall("VirtualFreeEx", "Ptr",hProc, "Ptr",pRB, "UPtr",0, "UInt",0x8000)
DllCall("CloseHandle", "Ptr",hProc)
}
DetectHiddenWindows(dhw)
return oTrayInfo
}
TrayIcon_Delete(idx, sTray := "Shell_TrayWnd") {
dhw := A_DetectHiddenWindows
DetectHiddenWindows(1)
idxTB := TrayIcon_GetTrayBar()
SendMessage(TB_DELETEBUTTON := 0x0416, idx, 0, "ToolbarWindow32" idxTB, "ahk_class " sTray)
SendMessage(0x001A, 0, 0,, "ahk_class " sTray)
DetectHiddenWindows(dhw)
}
icons := TrayIcon_GetInfo("")
info := ""
for item in icons
info .= item["idx"] ": " item["process"] "`n"
MsgBox info
icons := TrayIcon_GetInfo("someapp.exe")
If icons.Length = 1
TrayIcon_Delete(icons[1]["idx"])