/// <summary> /// The actual trayIconBuster /// </summary> /// <returns>The number of tray icons removed.</returns> public unsafe static uint RemovePhantomIcons() { bool is64bitWindows = Is64BitWindows(); ToolBarButton64 tbb64 = new ToolBarButton64(); ToolBarButton32 tbb32 = new ToolBarButton32(); TrayData td = new TrayData(); bool foundSomeExe = false; uint totalRemovedCount = 0; uint totalItemCount = 0; // for safety reasons we perform two passes: // pass1 = search for my own NotifyIcon // pass2 = search phantom icons and remove them // pass2 doesnt happen if pass1 fails lock (key) { // prevent concurrency problems for (int pass = 1; pass <= 2; pass++) { for (int kind = 0; kind < 2; kind++) { IntPtr hWnd = IntPtr.Zero; if (kind == 0) { // get the regular icon collection that exists on all Windows versions FindNestedWindow(ref hWnd, "Shell_TrayWnd"); FindNestedWindow(ref hWnd, "TrayNotifyWnd"); FindNestedWindow(ref hWnd, "SysPager"); FindNestedWindow(ref hWnd, "ToolbarWindow32"); } else { // get the hidden icon collection that exists since Windows 7 try { FindNestedWindow(ref hWnd, "NotifyIconOverflowWindow"); FindNestedWindow(ref hWnd, "ToolbarWindow32"); } catch { // fail silently, as NotifyIconOverflowWindow did not exist prior to Win7 break; } } // create an object so we can exchange data with other process using (LP_Process process = new LP_Process(hWnd)) { IntPtr remoteButtonPtr; if (is64bitWindows) { remoteButtonPtr = process.Allocate(tbb64); } else { remoteButtonPtr = process.Allocate(tbb32); } process.Allocate(td); uint itemCount = (uint)SendMessage(hWnd, TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero); //log("There are "+itemCount+" tray icons (some of them hidden)"); uint removedCount = 0; for (uint item = 0; item < itemCount; item++) { totalItemCount++; // index changes when previous items got removed ! uint item2 = item - removedCount; uint SOK = (uint)SendMessage(hWnd, TB_GETBUTTON, new IntPtr(item2), remoteButtonPtr); if (SOK != 1) { throw new ApplicationException("TB_GETBUTTON failed"); } if (is64bitWindows) { process.Read(tbb64, remoteButtonPtr); process.Read(td, tbb64.dwData); } else { process.Read(tbb32, remoteButtonPtr); process.Read(td, tbb32.dwData); } IntPtr hWnd2 = td.hWnd; if (hWnd2 == IntPtr.Zero) { throw new ApplicationException("Invalid window handle"); } using (LP_Process proc = new LP_Process(hWnd2)) { string filename = proc.GetImageFileName(); if (pass == 1 && filename != null) { filename = filename.ToLower(); if (filename.EndsWith(".exe")) { foundSomeExe = true; log("(kind=" + kind + ") found real icon created by: " + filename); break; } } // a phantom icon has no imagefilename if (pass == 2 && filename == null) { SOK = (uint)SendMessage(hWnd, TB_DELETEBUTTON, new IntPtr(item2), IntPtr.Zero); if (SOK != 1) { throw new ApplicationException("TB_DELETEBUTTON failed"); } removedCount++; totalRemovedCount++; } } } } } // next kind // if I did not see myself, I will not run the second // pass, which would try and remove phantom icons if (totalItemCount != 0 && !foundSomeExe) { throw new ApplicationException( "Failed to find any real icon"); } } } // release lock log(totalItemCount.ToString() + " icons found, " + totalRemovedCount + " icons removed"); return(totalRemovedCount); }
/// <summary> /// The actual trayIconBuster /// </summary> /// <returns>The number of tray icons removed.</returns> public static uint RemovePhantomIcons() { uint removedCount = 0; lock (key) { // prevent concurrency problems IntPtr hWnd = IntPtr.Zero; FindNestedWindow(ref hWnd, "Shell_TrayWnd"); FindNestedWindow(ref hWnd, "TrayNotifyWnd"); FindNestedWindow(ref hWnd, "SysPager"); FindNestedWindow(ref hWnd, "ToolbarWindow32"); // create an object so we can exchange data with other process using (LP_Process process = new LP_Process(hWnd)) { ToolBarButton tbb = new ToolBarButton(); IntPtr remoteButtonPtr = process.Allocate(tbb); TrayData td = new TrayData(); process.Allocate(td); uint itemCount = (uint)SendMessage(hWnd, TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero); log("There are " + itemCount + " tray icons (some of them hidden)"); bool foundSomeExe = false; // for safety reasons we perform two passes: // pass1 = search for my own NotifyIcon // pass2 = search phantom icons and remove them // pass2 doesnt happen if pass1 fails for (int pass = 1; pass <= 2; pass++) { for (uint item = 0; item < itemCount; item++) { // index changes when previous items got removed ! uint item2 = item - removedCount; uint SOK = (uint)SendMessage(hWnd, TB_GETBUTTON, new IntPtr(item2), remoteButtonPtr); if (SOK != 1) { throw new ApplicationException("TB_GETBUTTON failed"); } process.Read(tbb, remoteButtonPtr); process.Read(td, tbb.dwData); if (td.hWnd == IntPtr.Zero) { throw new ApplicationException("Invalid window handle"); } using (LP_Process proc = new LP_Process(td.hWnd)) { string filename = proc.GetImageFileName(); if (pass == 1 && filename != null) { filename = filename.ToLower(); if (filename.EndsWith(".exe")) { foundSomeExe = true; log("found real icon created by: " + filename); break; } } // a phantom icon has no imagefilename if (pass == 2 && filename == null) { SOK = (uint)SendMessage(hWnd, TB_DELETEBUTTON, new IntPtr(item2), IntPtr.Zero); if (SOK != 1) { throw new ApplicationException("TB_DELETEBUTTON failed"); } removedCount++; } } } // if I did not see myself, I will not run the second // pass, which would try and remove phantom icons if (!foundSomeExe) { throw new ApplicationException( "Failed to find any real icon"); } } } log(removedCount.ToString() + " icons removed"); } return(removedCount); }