Example #1
0
        /// <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);
        }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <summary>
        /// Removes any zombie icons (those whose processes no longer exist) from the notification tray.
        /// </summary>
        /// <returns>The number of tray icons removed.</returns>
        public static uint RemoveZombieIcons()
        {
            var  toolbarButton     = new ToolbarButton();
            var  extraData         = new ExtraButtonData();
            uint totalRemovedCount = 0;
            uint totalItemCount    = 0;

            foreach (var windowList in TrayWindowSearchList)
            {
                //Get a handle to the toolbar window
                IntPtr toolbarHandle = FindNestedWindow(windowList);
                if (toolbarHandle == IntPtr.Zero)
                {
                    Utilities.Log($"No window found for list: {windowList}");
                    continue;
                }

                //Use that handle to open the toolbar's process
                using (LP_Process process = new LP_Process(toolbarHandle))
                {
                    //Allocate shared memory in the process to store toolbar button data for us to read
                    IntPtr remoteButtonPtr = process.Allocate(toolbarButton);
                    process.Allocate(extraData);

                    //Ask the window how many buttons it contains so we can iterate over them
                    uint itemCount = (uint)SendMessage(toolbarHandle, TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero);
                    totalItemCount += itemCount;
                    Utilities.Log($"Found {itemCount} tray icons (some may be hidden)");
                    uint removedCount = 0;
                    for (uint item = 0; item < itemCount; item++)
                    {
                        //We remove items starting from the leftmost (#0), so for each item we have removed, the remaining items' indices
                        // will have 1 subtracted from them (since they all just got shifted left by 1).
                        uint index = item - removedCount;

                        //Get info for this toolbar button
                        if ((uint)SendMessage(toolbarHandle, TB_GETBUTTON, new IntPtr(index), remoteButtonPtr) == 0)
                        {
                            throw new ApplicationException("TB_GETBUTTON failed");
                        }
                        process.Read(toolbarButton, remoteButtonPtr);
                        process.Read(extraData, toolbarButton.dwData);

                        //Open the handle for this button to see if its parent process exists or not. If it has no parent, it's a zombie - kill it!
                        IntPtr buttonHandle = extraData.hWnd;
                        if (buttonHandle == IntPtr.Zero)
                        {
                            throw new ApplicationException("Invalid handle in tray button data");
                        }
                        using (LP_Process proc = new LP_Process(buttonHandle))
                        {
                            if (proc.ownerProcessID == 0)
                            {
                                RemoveIcon(extraData);
                                removedCount++;
                                totalRemovedCount++;
                            }
                        }
                    }
                }
            }

            Utilities.Log($"Done. {totalItemCount} icons found, {totalRemovedCount} icons removed.");
            return(totalRemovedCount);
        }