windzhou
11/20/2017 - 11:28 AM

ClearTrayIcon.cs

清楚系统托盘已经被杀死进程的图标

    public static class WindowsExtend
    {

        #region NativeMethod
        public const int MOUSEEVENTF_MOVE = 0x0001;
        public const int MOUSEEVENTF_RIGHTDOWN = 0x08;
        public const int MOUSEEVENTF_RIGHTUP = 0x10;
        public const int MOUSEEVENTF_LEFTDOWN = 0x02;
        public const int MOUSEEVENTF_LEFTUP = 0x04;

        const int WM_USER = 0x0400;
        const int TB_BUTTONCOUNT = (WM_USER + 24);
        const int TB_GETBUTTON = (WM_USER + 23);
        const int TB_GETBUTTONTEXTW = (WM_USER + 45);
        const int TB_DELETEBUTTON = (WM_USER + 22);
        const int TB_HIDEBUTTON = (WM_USER + 4);



        const int PROCESS_ALL_ACCESS = 0x1F0FFF;
        const int PAGE_READWRITE = 0x4;
        const int MEM_COMMIT = 0x1000;
        const int MEM_RESERVE = 0x2000;
        const int MEM_RELEASE = 0x8000;

        [DllImport("user32.dll")]
        public static extern bool SetCursorPos(int x, int y);

        [DllImport("user32")]
        public static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr WindowFromPoint(int x, int y);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetParent(IntPtr hWnd);

        [DllImport("user32.dll")]
        public extern static IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);

        [DllImport("User32.DLL")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        [DllImport("kernel32.dll")]
        static extern int OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll")]
        static extern int VirtualAllocEx(int hwnd, int lpaddress, int size, int type, int tect);

        [DllImport("kernel32.dll")]
        static extern int VirtualFreeEx(int hwnd, int lpAddress, int dwSize, int dwFreeType);

        [DllImport("kernel32.dll")]
        static extern int ReadProcessMemory(int hProcess, int lpBaseAddress, out TBBUTTON64 aTBInfo, int nSize, int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        static extern int ReadProcessMemory(int hProcess, int lpBaseAddress, out TBBUTTON32 aTBInfo, int nSize, int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        static extern int ReadProcessMemory(int hProcess, int lpBaseAddress, out TRAYDATA aTrayData, int nSize, int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        static extern int ReadProcessMemory(int hProcess, int lpBaseAddress, StringBuilder aBuffer, int nSize, int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        static extern int CloseHandle(int hObject);

        struct TBBUTTON32
        {
            int iBitmap;
            public int idCommand;
            byte fsState;
            byte fsStyle;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
            byte[] bReserved;
            public IntPtr dwData;
            IntPtr iString;
        }

        struct TBBUTTON64
        {
            int iBitmap;
            public int idCommand;
            byte fsState;
            byte fsStyle;
            [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6)]
            byte[] bReserved;
            public IntPtr dwData;
            IntPtr iString;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct TRAYDATA
        {
            public IntPtr hwnd;
            public int uID;
            public int uCallbackMessage;
            public int bReserved0;
            public int bReserved1;
            public IntPtr hIcon;
        }

        struct NOTIFYICONDATA
        {
            public int Size;
            public IntPtr HWnd;
            public int ID;
            public int Flags;
            public int CallbackMessage;
            public IntPtr HIcon;
        }

        [DllImport("shell32.dll")]
        static extern bool Shell_NotifyIcon(uint dwMessage, ref NOTIFYICONDATA pnid);
        #endregion

       

        #region ClearTrayIcon
        public static bool ClearKilledTrayIcon()
        {
            bool aResult = false;
            foreach (NOTIFYICONDATA aTrayData in SearchKilledTrayIcons())
            {
                NOTIFYICONDATA aData = aTrayData;
                aResult = true;
                Shell_NotifyIcon(2, ref aData);
            }
            return aResult;
        }

        private static List<NOTIFYICONDATA> SearchKilledTrayIcons()
        {
            List<NOTIFYICONDATA> aRestult = new List<NOTIFYICONDATA>();

            //Tray overflow panel
            IntPtr aNotifyIconOverflowWindowHwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "NotifyIconOverflowWindow", null);
            IntPtr aToolbarWindow32Hwnd = FindWindowEx(aNotifyIconOverflowWindowHwnd, IntPtr.Zero, "ToolbarWindow32", null);
            SearchInternelKilledTrayIcons(ref aRestult, aToolbarWindow32Hwnd);


            //Tray Tool bar
            IntPtr aWindowHwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", null);
            aWindowHwnd = FindWindowEx(aWindowHwnd, IntPtr.Zero, "TrayNotifyWnd", null);
            aWindowHwnd = FindWindowEx(aWindowHwnd, IntPtr.Zero, "SysPager", null);
            aWindowHwnd = FindWindowEx(aWindowHwnd, IntPtr.Zero, "ToolbarWindow32", null);
            SearchInternelKilledTrayIcons(ref aRestult, aWindowHwnd);

            return aRestult;
        }

        private static void SearchInternelKilledTrayIcons(ref List<NOTIFYICONDATA> aRestult, IntPtr aToolbarWindow32Hwnd)
        {
            int aProcessID;
            GetWindowThreadProcessId(aToolbarWindow32Hwnd, out aProcessID);
            int hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, aProcessID);
            if (hProcess > 0)
            {
                int aBufferPtr = 0;
                int aTitleBufferPtr = 0;
                aBufferPtr = VirtualAllocEx(hProcess, 0, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
                aTitleBufferPtr = VirtualAllocEx(hProcess, 0, 256, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);


                int btnCount = SendMessage(aToolbarWindow32Hwnd, TB_BUTTONCOUNT, 0, 0);
                for (int i = 0; i < btnCount; i++)
                {
                    int aIsOK = SendMessage(aToolbarWindow32Hwnd, TB_GETBUTTON, i, aBufferPtr);
                    if (aIsOK != 0)
                    {
                        aIsOK = 0;
                        int aTBButtonCommand = 0;
                        IntPtr aParentHwndPtr;
                        #region Read TBBUTTON
                        if (Environment.Is64BitOperatingSystem)
                        {
                            TBBUTTON64 aTBInfo = new TBBUTTON64();
                            aIsOK = ReadProcessMemory(hProcess, aBufferPtr, out aTBInfo, Marshal.SizeOf(aTBInfo), 0);
                            aTBButtonCommand = aTBInfo.idCommand;
                            aParentHwndPtr = aTBInfo.dwData;
                        }
                        else
                        {
                            TBBUTTON32 aTBInfo = new TBBUTTON32();
                            aIsOK = ReadProcessMemory(hProcess, aBufferPtr, out aTBInfo, Marshal.SizeOf(aTBInfo), 0);
                            aTBButtonCommand = aTBInfo.idCommand;
                            aParentHwndPtr = aTBInfo.dwData;
                        }
                        #endregion

                        if (aIsOK != 0)
                        {
                            //Tray Icon Title
                            //SendMessage(aToolbarWindow32Hwnd, TB_GETBUTTONTEXTW, aTBButtonCommand, aTitleBufferPtr);
                            //StringBuilder buffer = new StringBuilder(256);
                            //buffer.Clear();
                            //ReadProcessMemory(hProcess, aTitleBufferPtr, buffer, buffer.Capacity, 0);

                            aIsOK = 0;
                            TRAYDATA trayData = new TRAYDATA();
                            aIsOK = ReadProcessMemory(hProcess, aParentHwndPtr.ToInt32(), out trayData, Marshal.SizeOf(trayData), 0);
                            if (aIsOK != 0)
                            {
                                int dwProcessId = 0;
                                GetWindowThreadProcessId(trayData.hwnd, out dwProcessId);

                                if (dwProcessId == 0)
                                {
                                    NOTIFYICONDATA pnid = new NOTIFYICONDATA();
                                    pnid.Flags = 1 | 2 | 4;
                                    pnid.HWnd = trayData.hwnd;
                                    pnid.HIcon = trayData.hIcon;
                                    pnid.ID = trayData.uID;
                                    pnid.Size = Marshal.SizeOf(pnid);
                                    aRestult.Add(pnid);
                                }
                            }
                        }
                    }

                }

                VirtualFreeEx(hProcess, aTitleBufferPtr, 0, MEM_RELEASE);
                VirtualFreeEx(hProcess, aBufferPtr, 0, MEM_RELEASE);
                CloseHandle(hProcess);
            }
        }
        #endregion
    }