C# 如何获取具有systray图标的进程

C# 如何获取具有systray图标的进程,c#,c++,winapi,taskbar,C#,C++,Winapi,Taskbar,我正在尝试创建一个应用程序,以获取具有systray图标的进程列表。 我搜索了很多,找到了很多参考资料: 所有这些都是很好的资源,但对我来说最有用的是3和4 在这里,我们有一个例子来说明我想要什么 我想要具有systray图标的进程列表: 名为“AnVir任务管理器”的应用程序示例 使用link中的代码,我成功地遍历了systray按钮并查看每个按钮的文本: 但我不确定如何找到与每个trayicon相关的流程 在代码项目中,他提到可以帮助识别流程的信息是dwData,但问题是,当

我正在尝试创建一个应用程序,以获取具有systray图标的进程列表。
我搜索了很多,找到了很多参考资料:

  • 所有这些都是很好的资源,但对我来说最有用的是3和4

    在这里,我们有一个例子来说明我想要什么

    我想要具有systray图标的进程列表:
    名为“AnVir任务管理器”的应用程序示例

    使用link中的代码,我成功地遍历了systray按钮并查看每个按钮的文本:

    但我不确定如何找到与每个trayicon相关的流程

    在代码项目中,他提到可以帮助识别流程的信息是
    dwData
    ,但问题是,当我找到出现在Systray中的按钮时,它的
    dwData=0

    代码:

    Form1.cs 引擎.cs User32.cs
    我检查了32位的应用程序,发现
    dwData!=0
    。 这有助于我理解,问题在于使用64位时

    我替换了
    公共UInt32 dwData带有
    公共UInt64 dwData

        [ StructLayout( LayoutKind.Sequential ) ]
        internal struct TBBUTTON 
        {
            public Int32 iBitmap;
            public Int32 idCommand;
            public byte fsState;
            public byte fsStyle;
    //      [ MarshalAs( UnmanagedType.ByValArray, SizeConst=2 ) ]
    //      public byte[] bReserved;
            public byte bReserved1;
            public byte bReserved2;
           // public UInt32 dwData;
            public UInt64 dwData;
            public IntPtr iString;
        };  
    
    dwData
    现在大于零。
    我成功获取与流程关联的按钮的windows句柄并获取流程pid:

      // window handle
      fixed (byte* pLocalBuffer = localBuffer)
      {
       ...
       ipWindowHandle = new IntPtr(iWindowHandle);
    
       threadId = User32.GetWindowThreadProcessId(ipWindowHandle, out processId);
       data.setProcessPid(processId);
      }
    
    最后的结果是:

    此解决方案找不到与隐藏的系统托盘图标关联的进程,这是一个我需要探讨的新问题:)

    帮助我找到此解决方案想法的新参考资料:

    这是一个名为“mklencke”的人的评论,给出了64位的代码:

    typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
    
    BOOL IsWow64()
    {
        static bool isset = false;
        static BOOL bIsWow64 = FALSE;
    
        if (isset) {
            return bIsWow64;
        }
    
        //IsWow64Process is not available on all supported versions of Windows.
        //Use GetModuleHandle to get a handle to the DLL that contains the function
        //and GetProcAddress to get a pointer to the function if available.
    
        LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
            GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
    
        if(NULL != fnIsWow64Process)
        {
            if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
            {
                //TODO handle error?
                return FALSE;
            }
        }
    
        isset = true;
        return bIsWow64;
    }
    
    typedef struct _TBBUTTON64 {
        int iBitmap;
        int idCommand;
        BYTE fsState;
        BYTE fsStyle;
        BYTE bReserved[6];
        DWORD64 dwData;
        DWORD64 iString;
    } TBBUTTON64, NEAR* PTBBUTTON64, *LPTBBUTTON64;
    typedef const TBBUTTON64 *LPCTBBUTTON64;
    
    bool EnumSystemTray() { 
        bool bFound = false;
    
        // find system tray window
        HWND trayWnd = FindWindow(_T("Shell_TrayWnd"), NULL);
        if (trayWnd) {
            trayWnd = FindWindowEx(trayWnd, NULL,_T("TrayNotifyWnd"), NULL);
            if (trayWnd) {
                trayWnd = FindWindowEx(trayWnd, NULL,_T("SysPager"), NULL);
                if (trayWnd) {              
                    trayWnd = FindWindowEx(trayWnd, NULL,_T("ToolbarWindow32"), NULL);
                    bFound = true;
                }
            }
        }
    
        ASSERT(bFound);
    
        DWORD dwTrayPid;
        GetWindowThreadProcessId(trayWnd, &dwTrayPid);
    
        int count = (int) SendMessage(trayWnd, TB_BUTTONCOUNT, 0, 0);
    
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTrayPid);
        if (!hProcess) {
            return true;
        }
    
        BOOL bIsWow64 = IsWow64();
    
        SIZE_T dwSize = bIsWow64 ? sizeof(TBBUTTON64) : sizeof(TBBUTTON);
        LPVOID lpData = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
        if (!lpData) {
            return true;
        }
    
        // Loop through all systray icons
        for (int i = 0; i < count; i++) {
            HWND hwnd32;
    
            SendMessage(trayWnd, TB_GETBUTTON, i, (LPARAM)lpData);
            if ( bIsWow64 ) {
                // Try to read memory from 64-bit Explorer process. Hope the address of the traybar data is below 4GB
    
                TBBUTTON64 tbb;
                if (!ReadProcessMemory(hProcess, lpData, (LPVOID)&tbb, sizeof(TBBUTTON64), NULL)) {
                    continue;
                }
    
                DWORD64 hwnd;
    
                // First member of TRAYDATA structure is HWND, so we can just use the address of the struct to read the member
                if (!ReadProcessMemory(hProcess, (LPCVOID)tbb.dwData, (LPVOID)&hwnd, sizeof(DWORD64), NULL)) {
                    continue;
                }
    
                // Hope this does not get truncated, but we shouldn't have that many windows
                hwnd32 = (HWND)hwnd;
            } else {
                TBBUTTON tbb;
                if (!ReadProcessMemory(hProcess, lpData, (LPVOID)&tbb, sizeof(TBBUTTON), NULL)) {
                    continue;
                }
    
                DWORD32 hwnd;
    
                // First member of TRAYDATA structure is HWND, so we can just use the address of the struct to read the member
                if (!ReadProcessMemory(hProcess, (LPCVOID)tbb.dwData, (LPVOID)&hwnd, sizeof(DWORD32), NULL)) {
                    continue;
                }
    
                hwnd32 = (HWND)hwnd;
            }
    
            DWORD dwProcessId = 0;
            GetWindowThreadProcessId(hwnd32, &dwProcessId);
    
            // XXX - DO SOMETHING WITH dwProcessId
        }
    
        VirtualFreeEx(hProcess, lpData, NULL, MEM_RELEASE);
    
        return true;
    }
    
    typedef BOOL(WINAPI*LPFN_iswow64进程)(句柄,PBOOL);
    BOOL IsWow64()
    {
    静态布尔isset=假;
    静态布尔bIsWow64=假;
    如果(isset){
    返回bIsWow64;
    }
    //ISWOW64进程在所有受支持的Windows版本上都不可用。
    //使用GetModuleHandle获取包含函数的DLL的句柄
    //和GetProcAddress获取指向函数的指针(如果可用)。
    LPFN_iswow64进程fniswow64进程=(LPFN_iswow64进程)GetProcAddress(
    GetModuleHandle(文本(“内核32”),“IsWow64Process”);
    if(NULL!=fnIsWow64Process)
    {
    if(!fniswow64进程(GetCurrentProcess(),&bIsWow64))
    {
    //TODO处理错误?
    返回FALSE;
    }
    }
    isset=真;
    返回bIsWow64;
    }
    类型定义结构\u TBBUTTON64{
    国际iBitmap;
    int-idCommand;
    字节状态;
    字节样式;
    字节[6];
    DWORD64数据;
    DWORD64 iString;
    }TBBUTTON64,靠近*PTBBUTTON64,*LPTBBUTTON64;
    类型定义常量TBBUTTON64*LPCTBBUTTON64;
    bool EnumSystemTray(){
    boolbfound=false;
    //查找系统托盘窗口
    HWND trayWnd=FindWindow(_T(“Shell_trayWnd”),NULL;
    如果(trayWnd){
    trayWnd=FindWindowEx(trayWnd,NULL,_T(“TrayNotifyWnd”),NULL);
    如果(trayWnd){
    trayWnd=FindWindowEx(trayWnd,NULL,_T(“SysPager”),NULL);
    if(trayWnd){
    trayWnd=FindWindowEx(trayWnd,NULL,_T(“ToolbarWindow32”),NULL);
    bFound=真;
    }
    }
    }
    断言(bFound);
    德沃德·德特莱皮德;
    GetWindowThreadProcessId(trayWnd和DWTrayId);
    int count=(int)SendMessage(trayWnd,TB_按钮计数,0,0);
    HANDLE hProcess=OpenProcess(PROCESS\u ALL\u ACCESS,FALSE,dwTrayPid);
    如果(!hProcess){
    返回true;
    }
    BOOL bIsWow64=IsWow64();
    尺寸=bIsWow64?尺寸(TBBUTTON64):尺寸(TBBUTTON);
    LPVOID lpData=VirtualAllocEx(hProcess,NULL,dwSize,MEM\u COMMIT,PAGE\u READWRITE);
    如果(!lpData){
    返回true;
    }
    //循环浏览所有systray图标
    for(int i=0;i
    您说过您使用链接6获取名称。但是那篇CodeProject文章还指定了如何获取其余信息,包括流程内容。这对你不起作用吗?@VladFeinstein,他提到“所以我看了一下dwData字段,它们似乎是指针。好的,到目前为止。然后我看了一下它们指向的内存,它们在那里:第一个字段存储窗口句柄”。------但是当我
    using System;
    using System.Runtime.InteropServices;
    using System.Text;
    
    namespace Common
    {
        internal enum GW : uint
        {
            HWNDFIRST        = 0,
            HWNDLAST         = 1,
            HWNDNEXT         = 2,
            HWNDPREV         = 3,
            OWNER            = 4,
            CHILD            = 5,
            MAX              = 6
        }
    
        internal class ICON
        {
            public const UInt32 SMALL          = 0;
            public const UInt32 BIG            = 1;
            public const UInt32 SMALL2         = 2; // XP+
        }
    
        internal enum MB : uint
        {
            SimpleBeep      = 0xFFFFFFFF,
            IconAsterisk    = 0x00000040,
            IconWarning     = 0x00000030,
            IconError       = 0x00000010,
            IconQuestion    = 0x00000020,
            OK              = 0x00000000
        }
    
        internal class SW
        {
            public const int HIDE               = 0;
            public const int SHOWNORMAL         = 1;
            public const int NORMAL             = 1;
            public const int SHOWMINIMIZED      = 2;
            public const int SHOWMAXIMIZED      = 3;
            public const int MAXIMIZE           = 3;
            public const int SHOWNOACTIVATE     = 4;
            public const int SHOW               = 5;
            public const int MINIMIZE           = 6;
            public const int SHOWMINNOACTIVE    = 7;
            public const int SHOWNA             = 8;
            public const int RESTORE            = 9;
            public const int SHOWDEFAULT        = 10;
            public const int FORCEMINIMIZE      = 11;
            public const int MAX                = 11;
        }
    
        internal class TB
        {
            public const uint GETBUTTON       = WM.USER + 23 ;
            public const uint BUTTONCOUNT     = WM.USER + 24 ;
            public const uint CUSTOMIZE       = WM.USER + 27 ;
            public const uint GETBUTTONTEXTA  = WM.USER + 45 ;
            public const uint GETBUTTONTEXTW  = WM.USER + 75 ;
        }
    
        internal class TBSTATE
        {
            public const uint CHECKED        =  0x01 ;
            public const uint PRESSED        =  0x02 ;
            public const uint ENABLED        =  0x04 ;
            public const uint HIDDEN         =  0x08 ;
            public const uint INDETERMINATE  =  0x10 ;
            public const uint WRAP           =  0x20 ;
            public const uint ELLIPSES       =  0x40 ;
            public const uint MARKED         =  0x80 ;
        }
    
        internal class WM
        {
            public const uint CLOSE   = 0x0010;
            public const uint GETICON = 0x007F;
            public const uint KEYDOWN = 0x0100;
            public const uint COMMAND = 0x0111;
            public const uint USER    = 0x0400; // 0x0400 - 0x7FFF
            public const uint APP     = 0x8000; // 0x8000 - 0xBFFF
        }
    
        internal class GCL
        {
            public const int MENUNAME       = - 8;
            public const int HBRBACKGROUND  = -10;
            public const int HCURSOR        = -12;
            public const int HICON          = -14;
            public const int HMODULE        = -16;
            public const int CBWNDEXTRA     = -18;
            public const int CBCLSEXTRA     = -20;
            public const int WNDPROC        = -24;
            public const int STYLE          = -26;
            public const int ATOM           = -32;
            public const int HICONSM        = -34;
    
            // GetClassLongPtr ( 64-bit )
            private const int GCW_ATOM           = -32;
            private const int GCL_CBCLSEXTRA     = -20;
            private const int GCL_CBWNDEXTRA     = -18;
            private const int GCLP_MENUNAME      = - 8;
            private const int GCLP_HBRBACKGROUND = -10;
            private const int GCLP_HCURSOR       = -12;
            private const int GCLP_HICON         = -14;
            private const int GCLP_HMODULE       = -16;
            private const int GCLP_WNDPROC       = -24;
            private const int GCLP_HICONSM       = -34;
            private const int GCL_STYLE          = -26;
    
        }
    
        [ StructLayout( LayoutKind.Sequential ) ]
        internal struct TBBUTTON 
        {
            public Int32 iBitmap;
            public Int32 idCommand;
            public byte fsState;
            public byte fsStyle;
    //      [ MarshalAs( UnmanagedType.ByValArray, SizeConst=2 ) ]
    //      public byte[] bReserved;
            public byte bReserved1;
            public byte bReserved2;
            public UInt32 dwData;
            public IntPtr iString;
        };
    
        internal class User32
        {
            private User32() {}
    
    //      public const UInt32 WM_USER = 0x0400;
    
    //      public const UInt32 WM_KEYDOWN = 0x0100;
            [DllImport("user32.dll")]
            public static extern IntPtr SendMessage(
                IntPtr hWnd,
                UInt32 msg,
                IntPtr wParam,
                IntPtr lParam );
    
            [DllImport("user32.dll")]
            public static extern UInt32 SendMessage(
                IntPtr hWnd,
                UInt32 msg,
                UInt32 wParam,
                UInt32 lParam );
    
            [ DllImport( "User32.dll" ) ]
            public static extern bool PostMessage
            (
                IntPtr hWnd,
                UInt32 Msg,
                IntPtr wParam,
                IntPtr lParam
            );
    
            [ DllImport( "User32.dll" ) ]
            public static extern bool PostMessage
            (
                IntPtr hWnd,
                UInt32 Msg,
                UInt32 wParam,
                UInt32 lParam
            );
    
            [ DllImport( "User32.dll" ) ]
            public static extern bool MessageBeep
            (
                MB BeepType
            );
    
            [DllImport("user32.dll")]
            public static extern bool ShowWindow
            (
                IntPtr hWnd,
                int nCmdShow
            );
    
            [DllImport("user32.dll")]
            public static extern bool SetForegroundWindow
            (
                IntPtr hWnd
            );
    
    
            [ DllImport( "User32.dll" ) ]
            public static extern IntPtr GetDesktopWindow
            (
            );
    
            [ DllImport( "user32.dll", CharSet = CharSet.Unicode ) ]
            public static extern IntPtr FindWindowEx(
                IntPtr hwndParent,
                IntPtr hwndChildAfter,
                string lpszClass,
                string lpszWindow);
    
            [ DllImport( "User32.dll" ) ]
            public static extern IntPtr GetWindow
            (
                IntPtr hWnd,
                GW     uCmd
            );
    
            [ DllImport( "User32.dll" ) ]
            public static extern Int32 GetWindowTextLength
            (
                IntPtr hWnd
            );
    
            [ DllImport( "User32.dll", SetLastError = true, CharSet = CharSet.Auto ) ]
            public static extern Int32 GetWindowText
            (
                IntPtr hWnd,
                out StringBuilder lpString,
                Int32 nMaxCount
            );
    
            [ DllImport( "User32.dll", CharSet = CharSet.Auto ) ]
            public static extern Int32 GetClassName
            (
                IntPtr hWnd,
                out StringBuilder lpClassName,
                Int32 nMaxCount
            );
    
    //      [ DllImport( "user32.dll", EntryPoint = "GetClassLongPtrW" ) ]
            [ DllImport( "user32.dll" ) ]
            public static extern UInt32 GetClassLong
            (
                IntPtr hWnd,
                int nIndex
            );
    
            [DllImport("user32.dll")]
            public static extern uint SetClassLong
            (
                IntPtr hWnd,
                int nIndex,
                uint dwNewLong
            );
    
            [ DllImport( "User32.dll", CharSet=CharSet.Auto ) ]
            public static extern UInt32 GetWindowThreadProcessId
            (
                IntPtr hWnd,
    //          [ MarshalAs( UnmanagedType.
                out UInt32 lpdwProcessId
            );
    
    
            // Systray icons
            //[DllImport("user32.dll", SetLastError = true)]
           // public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpClassName, string lpWindowName);
    
            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
    
    
    
    
        }
    }
    
        [ StructLayout( LayoutKind.Sequential ) ]
        internal struct TBBUTTON 
        {
            public Int32 iBitmap;
            public Int32 idCommand;
            public byte fsState;
            public byte fsStyle;
    //      [ MarshalAs( UnmanagedType.ByValArray, SizeConst=2 ) ]
    //      public byte[] bReserved;
            public byte bReserved1;
            public byte bReserved2;
           // public UInt32 dwData;
            public UInt64 dwData;
            public IntPtr iString;
        };  
    
      // window handle
      fixed (byte* pLocalBuffer = localBuffer)
      {
       ...
       ipWindowHandle = new IntPtr(iWindowHandle);
    
       threadId = User32.GetWindowThreadProcessId(ipWindowHandle, out processId);
       data.setProcessPid(processId);
      }
    
    typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
    
    BOOL IsWow64()
    {
        static bool isset = false;
        static BOOL bIsWow64 = FALSE;
    
        if (isset) {
            return bIsWow64;
        }
    
        //IsWow64Process is not available on all supported versions of Windows.
        //Use GetModuleHandle to get a handle to the DLL that contains the function
        //and GetProcAddress to get a pointer to the function if available.
    
        LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
            GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
    
        if(NULL != fnIsWow64Process)
        {
            if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
            {
                //TODO handle error?
                return FALSE;
            }
        }
    
        isset = true;
        return bIsWow64;
    }
    
    typedef struct _TBBUTTON64 {
        int iBitmap;
        int idCommand;
        BYTE fsState;
        BYTE fsStyle;
        BYTE bReserved[6];
        DWORD64 dwData;
        DWORD64 iString;
    } TBBUTTON64, NEAR* PTBBUTTON64, *LPTBBUTTON64;
    typedef const TBBUTTON64 *LPCTBBUTTON64;
    
    bool EnumSystemTray() { 
        bool bFound = false;
    
        // find system tray window
        HWND trayWnd = FindWindow(_T("Shell_TrayWnd"), NULL);
        if (trayWnd) {
            trayWnd = FindWindowEx(trayWnd, NULL,_T("TrayNotifyWnd"), NULL);
            if (trayWnd) {
                trayWnd = FindWindowEx(trayWnd, NULL,_T("SysPager"), NULL);
                if (trayWnd) {              
                    trayWnd = FindWindowEx(trayWnd, NULL,_T("ToolbarWindow32"), NULL);
                    bFound = true;
                }
            }
        }
    
        ASSERT(bFound);
    
        DWORD dwTrayPid;
        GetWindowThreadProcessId(trayWnd, &dwTrayPid);
    
        int count = (int) SendMessage(trayWnd, TB_BUTTONCOUNT, 0, 0);
    
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTrayPid);
        if (!hProcess) {
            return true;
        }
    
        BOOL bIsWow64 = IsWow64();
    
        SIZE_T dwSize = bIsWow64 ? sizeof(TBBUTTON64) : sizeof(TBBUTTON);
        LPVOID lpData = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
        if (!lpData) {
            return true;
        }
    
        // Loop through all systray icons
        for (int i = 0; i < count; i++) {
            HWND hwnd32;
    
            SendMessage(trayWnd, TB_GETBUTTON, i, (LPARAM)lpData);
            if ( bIsWow64 ) {
                // Try to read memory from 64-bit Explorer process. Hope the address of the traybar data is below 4GB
    
                TBBUTTON64 tbb;
                if (!ReadProcessMemory(hProcess, lpData, (LPVOID)&tbb, sizeof(TBBUTTON64), NULL)) {
                    continue;
                }
    
                DWORD64 hwnd;
    
                // First member of TRAYDATA structure is HWND, so we can just use the address of the struct to read the member
                if (!ReadProcessMemory(hProcess, (LPCVOID)tbb.dwData, (LPVOID)&hwnd, sizeof(DWORD64), NULL)) {
                    continue;
                }
    
                // Hope this does not get truncated, but we shouldn't have that many windows
                hwnd32 = (HWND)hwnd;
            } else {
                TBBUTTON tbb;
                if (!ReadProcessMemory(hProcess, lpData, (LPVOID)&tbb, sizeof(TBBUTTON), NULL)) {
                    continue;
                }
    
                DWORD32 hwnd;
    
                // First member of TRAYDATA structure is HWND, so we can just use the address of the struct to read the member
                if (!ReadProcessMemory(hProcess, (LPCVOID)tbb.dwData, (LPVOID)&hwnd, sizeof(DWORD32), NULL)) {
                    continue;
                }
    
                hwnd32 = (HWND)hwnd;
            }
    
            DWORD dwProcessId = 0;
            GetWindowThreadProcessId(hwnd32, &dwProcessId);
    
            // XXX - DO SOMETHING WITH dwProcessId
        }
    
        VirtualFreeEx(hProcess, lpData, NULL, MEM_RELEASE);
    
        return true;
    }