Being without a cleaner for my notification tray eventually got me annoyed enough...
For Windows 7 64 bit & AutoHotkey_L UNICODE 64 Bit ONLY!!
EDIT Designed for 'Always show all icons and notifications' mode.
TrayIcon_Cleanup()
Verry lightly tested!!! Works for me!
Possible Bug Alert!!
This morning (after working for 3 days) I had many blank/empty tray icons, probably due to this script.
But it doesn't get called that often?
They went away once mouse-overed.
UPDATE:
Was the script, when I ran it I got one blank icon for each existing one.
However on reboot, it went away.
I had not rebooted since debugging this script, I'm putting this one down to Windows twisted nickers.
If nothing happens in a while I'll remove the above.
Code:
;#NoTrayIcon ; to test standalone, uncomment these four lines
;#SingleInstance, force
;TrayIcon_CleanUp()
;Return
TrayIcon_CleanUp()
{ ; Remove abandoned icons in notification tray, such as left behine by "Process Close"
; Windows 7 64 bit & AutoHotkey_L UNICODE 64Bit ONLY version!!!!!!!
; v0-5 - extensive change for Win7/64
; Originally based on TrayIcon by Sean @ http://www.autohotkey.com/forum/topic17314.html
;
DetectHiddenWindows, On
TBW:=GetTrayBar()
WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd
hProc := DllCall("OpenProcess"
, "Uint", 0x38
, "int", 0
, "Uint", pidTaskbar)
pRB := DllCall("VirtualAllocEx"
, "Uint", hProc
, "Uint", 0
, "Uint", 32
, "Uint", 0x1000
, "Uint", 0x4)
VarSetCapacity(btn, 32, 0)
VarSetCapacity(nfo, 32, 0)
SendMessage, 0x418, 0, 0, ToolbarWindow32%TBW%
, ahk_class Shell_TrayWnd ; TB_BUTTONCOUNT
Counter := ErrorLevel
Loop, %Counter%
{
Counter-- ; Must count DOWN as the zero-based indexes change if you remove a lower one
;
SendMessage, 0x417, Counter, pRB, ToolbarWindow32%TBW%
, ahk_class Shell_TrayWnd ; TB_GETBUTTON
VarSetCapacity(bread,8,32)
VarSetCapacity(bread2,8,32)
DllCall("ReadProcessMemory", "int64", hProc
,"int64", pRB
,"int64", &btn
,"int64", 32
,"int64", &bread)
dwData := Numget(btn,0x10,"int64") ; see struct way below
DllCall("ReadProcessMemory" , "int64", hProc
, "int64", dwData
, "int64", &nfo
, "int64", 32
, "int64", &bread2)
hWnd := NumGet(nfo, 0, "int64")
if !WinExist("ahk_id " . hWnd) {
SendMessage, 1046, Counter , 0, ToolbarWindow32%TBW% ; zero-based index of button
, ahk_class Shell_TrayWnd ; TB_DELETEBUTTON
}
} ; /Loop
DllCall("VirtualFreeEx"
, "Uint", hProc
, "Uint", pRB
, "Uint", 0
, "Uint", 0x8000)
DllCall("CloseHandle", "Uint", hProc)
Return sTrayIcon_CleanUp
}
GetTrayBar() ; Get the notification area traybar number. For Windows 7 ONLY!!!!!!!
{ ; Sorry, forgot who I got this approach from. Note it works, I confirmed hWnd
ControlGet, hParent, hWnd,, TrayNotifyWnd1 , ahk_class Shell_TrayWnd
ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent%
Loop
{
ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd
If Not hWnd
Break
Else If hWnd = %hChild%
{
idxTB := A_Index
Break
}
}
Return idxTB
}
; Structs for W7/64
/*typedef struct {
int iBitmap; x00
int idCommand; x04
BYTE fsState; x08
BYTE fsStyle; x09
#ifdef _WIN64
BYTE bReserved[6]; x0A
#else
#if defined(_WIN32)
BYTE bReserved[2]; x0A
#endif
#endif WIN32/WIN64
DWORD_PTR dwData; x0C/x10 d12/d16
INT_PTR iString; x10/x18 d16/d24
x14/x20 d20/d32
} TBBUTTON, *PTBBUTTON, *LPTBBUTTON;
*/
/*
BOOL WINAPI ReadProcessMemory(
__in HANDLE hProcess, 64
__in LPCVOID lpBaseAddress, 64
__out LPVOID lpBuffer,64
__in SIZE_T nSize, 64
__out SIZE_T *lpNumberOfBytesRead 64
);
*/
Someone can use it to update the other TrayIcon stuff if they wish.
EDIT
Works on Ahk 1.0.92.02
I just saw the change log:
"1.0.97.01 - April 2, 2011
Fixed the 64-bit build to not truncate HWNDs or SendMessage/PostMessage params to 32 bits."
I suspect my code will not work.

I'll get around to it.... eventually... EDIT Had a quick look, you could be lucky.