我正在尝试创建获取具有systray图标的进程列表的应用程序。
我搜索了很多,发现了一些引用文献:

  • http://www.raymond.cc/blog/find-out-what-program-are-running-at-windows-system-tray/
  • https://superuser.com/questions/708674/how-to-find-out-what-process-a-system-tray-icon-corresponds-to
  • Which Windows process is displaying a given taskbar system tray icon?
  • https://social.msdn.microsoft.com/Forums/vstudio/en-US/53e27f60-37af-406f-bbdc-45db2bd3dee6/how-to-find-a-system-tray-process
  • https://social.msdn.microsoft.com/Forums/vstudio/en-US/4c4f60ce-3573-433d-994e-9c17f95187f0/finding-which-applications-and-services-are-listed-in-the-system-tray?forum=csharpgeneral
  • http://www.codeproject.com/Articles/10497/A-tool-to-order-the-window-buttons-in-your-taskbar
  • Get ToolTip Text from Icon in System Tray

  • 它们都是很好的资源,但对我来说最有用的是3和4。

    1中,有一个我想要的示例。

    我想要具有systray图标的进程列表:
    c# - 如何获取具有系统托盘图标的进程-LMLPHP
    名为“AnVir任务管理器”的应用程序示例

    使用链接6中的代码,我成功地遍历了系统托盘按钮,并看到了每个按钮的文本:
    c# - 如何获取具有系统托盘图标的进程-LMLPHP

    但是我不确定如何找到与每个纸盘图标相关的过程。

    他在代码项目中提到可以帮助识别过程的信息是dwData,但是问题是当我发现Systray中出现的按钮时,它的dwData = 0是:
    c# - 如何获取具有系统托盘图标的进程-LMLPHP

    代码:

    Form1.cs
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace SystrayIcons
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                Engine.findProcessInSystray();
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Engine.findProcessInSystray();
            }
        }
    }
    

    Engine.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    using Common;
    using System.Diagnostics;
    using System.Collections;
    
    namespace SystrayIcons
    {
    
        static class Engine
        {
            static public void findProcessInSystray()
            {
                IntPtr systemTrayHandle = GetSystemTrayHandle();
    
                UInt32 count = User32.SendMessage(systemTrayHandle, TB.BUTTONCOUNT, 0, 0);
    
                ArrayList tbButtons = new ArrayList();
                List<TBBUTTON> tbButtons2 = new  List<TBBUTTON>();
    
                for (int i = 0; i < count; i++)
                {
                    TBBUTTON tbButton = new TBBUTTON();
                    string text = String.Empty;
                    IntPtr ipWindowHandle = IntPtr.Zero;
    
                    bool b = GetTBButton(systemTrayHandle, i, ref tbButton, ref text, ref ipWindowHandle);
                   // if (tbButton.iBitmap != 0)
                   if(tbButton.dwData != 0)
                    {
                        tbButtons.Add(tbButton);
                        tbButtons2.Add(tbButton);
                    }
                }
    
    
    
               // CreateImageList();
    
                System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcesses();
                foreach (System.Diagnostics.Process process in processes)
                {
                    if (process.MainWindowHandle == systemTrayHandle)
                    {
    
                    }
    
                }
    
    
    
            }
    
            static IntPtr GetSystemTrayHandle()
            {
                IntPtr hWndTray = User32.FindWindow("Shell_TrayWnd", null);
                if (hWndTray != IntPtr.Zero)
                {
                    hWndTray = User32.FindWindowEx(hWndTray, IntPtr.Zero, "TrayNotifyWnd", null);
                    if (hWndTray != IntPtr.Zero)
                    {
                        hWndTray = User32.FindWindowEx(hWndTray, IntPtr.Zero, "SysPager", null);
                        if (hWndTray != IntPtr.Zero)
                        {
                            hWndTray = User32.FindWindowEx(hWndTray, IntPtr.Zero, "ToolbarWindow32", null);
                            return hWndTray;
                        }
                    }
                }
    
                return IntPtr.Zero;
            }
    
    
            public static unsafe bool GetTBButton(IntPtr hToolbar, int i, ref TBBUTTON tbButton, ref string text, ref IntPtr ipWindowHandle)
            {
                // One page
                const int BUFFER_SIZE = 0x1000;
    
                byte[] localBuffer = new byte[BUFFER_SIZE];
    
                UInt32 processId = 0;
                UInt32 threadId = User32.GetWindowThreadProcessId(hToolbar, out processId);
    
                IntPtr hProcess = Kernel32.OpenProcess(ProcessRights.ALL_ACCESS, false, processId);
                if (hProcess == IntPtr.Zero) { Debug.Assert(false); return false; }
    
                IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx(
                    hProcess,
                    IntPtr.Zero,
                    new UIntPtr(BUFFER_SIZE),
                    MemAllocationType.COMMIT,
                    MemoryProtection.PAGE_READWRITE);
    
                if (ipRemoteBuffer == IntPtr.Zero) { Debug.Assert(false); return false; }
    
                // TBButton
                fixed (TBBUTTON* pTBButton = &tbButton)
                {
                    IntPtr ipTBButton = new IntPtr(pTBButton);
    
                    int b = (int)User32.SendMessage(hToolbar, TB.GETBUTTON, (IntPtr)i, ipRemoteBuffer);
                    if (b == 0) { Debug.Assert(false); return false; }
    
                    // this is fixed
                    Int32 dwBytesRead = 0;
                    IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
    
                    bool b2 = Kernel32.ReadProcessMemory(
                        hProcess,
                        ipRemoteBuffer,
                        ipTBButton,
                        new UIntPtr((uint)sizeof(TBBUTTON)),
                        ipBytesRead);
    
    
                    if (!b2) { Debug.Assert(false); return false; }
                }
    
                // button text
                fixed (byte* pLocalBuffer = localBuffer)
                {
                    IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer);
    
                    int chars = (int)User32.SendMessage(hToolbar, TB.GETBUTTONTEXTW, (IntPtr)tbButton.idCommand, ipRemoteBuffer);
                    if (chars == -1) { Debug.Assert(false); return false; }
    
                    // this is fixed
                    Int32 dwBytesRead = 0;
                    IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
    
                    bool b4 = Kernel32.ReadProcessMemory(
                        hProcess,
                        ipRemoteBuffer,
                        ipLocalBuffer,
                        new UIntPtr(BUFFER_SIZE),
                        ipBytesRead);
    
                    if (!b4) { Debug.Assert(false); return false; }
    
                    text = Marshal.PtrToStringUni(ipLocalBuffer, chars);
    
                    if (text == " ") text = String.Empty;
                }
    
    
    
    // window handle
                fixed (byte* pLocalBuffer = localBuffer)
                {
                    IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer);
    
                    // this is in the remote virtual memory space
                    IntPtr ipRemoteData = new IntPtr(tbButton.dwData);
    
                    // this is fixed
                    Int32 dwBytesRead = 0;
                    IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
    
                    bool b4 = Kernel32.ReadProcessMemory(
                        hProcess,
                        ipRemoteData,
                        ipLocalBuffer,
                        new UIntPtr(4),
                        ipBytesRead);
    
                    if (!b4) { Debug.Assert(false); return false; }
    
                    if (dwBytesRead != 4) { Debug.Assert(false); return false; }
    
                    Int32 iWindowHandle = BitConverter.ToInt32(localBuffer, 0);
                    if (iWindowHandle == -1) { Debug.Assert(false); }//return false; }
    
                    ipWindowHandle = new IntPtr(iWindowHandle);
                }
    
                Kernel32.VirtualFreeEx(
                    hProcess,
                    ipRemoteBuffer,
                    UIntPtr.Zero,
                    MemAllocationType.RELEASE);
    
    
                Kernel32.CloseHandle(hProcess);
                return true;
            }
    
        }
    }
    

    Kernel32.cs
    using System;
    using System.Runtime.InteropServices;
    
    namespace Common
    {
    
    //-----------------------------------------------------------------------------
    // Structures
    
        [StructLayout(LayoutKind.Sequential)]
        internal struct SYSTEM_INFO
        {
            public _PROCESSOR_INFO_UNION uProcessorInfo;
            public uint dwPageSize;
            public uint lpMinimumApplicationAddress;
            public uint lpMaximumApplicationAddress;
            public uint dwActiveProcessorMask;
            public uint dwNumberOfProcessors;
            public uint dwProcessorType;
            public uint dwAllocationGranularity;
            public uint dwProcessorLevel;
            public uint dwProcessorRevision;
        }
    
        [StructLayout(LayoutKind.Explicit)]
        internal struct _PROCESSOR_INFO_UNION
        {
            [FieldOffset(0)]
            public uint dwOemId;
            [FieldOffset(0)]
            public ushort wProcessorArchitecture;
            [FieldOffset(2)]
            public ushort wReserved;
        }
    
        [ StructLayout( LayoutKind.Sequential )]
        internal struct BY_HANDLE_FILE_INFORMATION
        {
            public UInt32 dwFileAttributes;
            public FILETIME ftCreationTime;
            public FILETIME ftLastAccessTime;
            public FILETIME ftLastWriteTime;
            public UInt32 dwVolumeSerialNumber;
            public UInt32 nFileSizeHigh;
            public UInt32 nFileSizeLow;
            public UInt32 nNumberOfLinks;
            public UInt32 nFileIndexHigh;
            public UInt32 nFileIndexLow;
        }
    
        [ StructLayout( LayoutKind.Sequential )]
        internal class MEMORYSTATUSEX
        {
            public Int32 Length;
            public Int32 MemoryLoad;
            public UInt64 TotalPhysical;
            public UInt64 AvailablePhysical;
            public UInt64 TotalPageFile;
            public UInt64 AvailablePageFile;
            public UInt64 TotalVirtual;
            public UInt64 AvailableVirtual;
            public UInt64 AvailableExtendedVirtual;
    
            public MEMORYSTATUSEX() { Length = Marshal.SizeOf( this ); }
    
            private void StopTheCompilerComplaining()
            {
                Length = 0;
                MemoryLoad = 0;
                TotalPhysical = 0;
                AvailablePhysical = 0;
                TotalPageFile = 0;
                AvailablePageFile = 0;
                TotalVirtual = 0;
                AvailableVirtual = 0;
                AvailableExtendedVirtual = 0;
            }
        }
    
    //-----------------------------------------------------------------------------
    // Constants
    
        internal class ProcessRights
        {
            public const UInt32 TERMINATE         = 0x0001  ;
            public const UInt32 CREATE_THREAD     = 0x0002  ;
            public const UInt32 SET_SESSIONID     = 0x0004  ;
            public const UInt32 VM_OPERATION      = 0x0008  ;
            public const UInt32 VM_READ           = 0x0010  ;
            public const UInt32 VM_WRITE          = 0x0020  ;
            public const UInt32 DUP_HANDLE        = 0x0040  ;
            public const UInt32 CREATE_PROCESS    = 0x0080  ;
            public const UInt32 SET_QUOTA         = 0x0100  ;
            public const UInt32 SET_INFORMATION   = 0x0200  ;
            public const UInt32 QUERY_INFORMATION = 0x0400  ;
            public const UInt32 SUSPEND_RESUME    = 0x0800  ;
    
            private const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
            private const UInt32 SYNCHRONIZE              = 0x00100000;
    
            public const UInt32 ALL_ACCESS        = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF;
        }
    
        internal class MemoryProtection
        {
            public const UInt32 PAGE_NOACCESS          =  0x01     ;
            public const UInt32 PAGE_READONLY          =  0x02     ;
            public const UInt32 PAGE_READWRITE         =  0x04     ;
            public const UInt32 PAGE_WRITECOPY         =  0x08     ;
            public const UInt32 PAGE_EXECUTE           =  0x10     ;
            public const UInt32 PAGE_EXECUTE_READ      =  0x20     ;
            public const UInt32 PAGE_EXECUTE_READWRITE =  0x40     ;
            public const UInt32 PAGE_EXECUTE_WRITECOPY =  0x80     ;
            public const UInt32 PAGE_GUARD             = 0x100     ;
            public const UInt32 PAGE_NOCACHE           = 0x200     ;
            public const UInt32 PAGE_WRITECOMBINE      = 0x400     ;
        }
    
        internal class MemAllocationType
        {
            public const UInt32 COMMIT       =     0x1000     ;
            public const UInt32 RESERVE      =     0x2000     ;
            public const UInt32 DECOMMIT     =     0x4000     ;
            public const UInt32 RELEASE      =     0x8000     ;
            public const UInt32 FREE         =    0x10000     ;
            public const UInt32 PRIVATE      =    0x20000     ;
            public const UInt32 MAPPED       =    0x40000     ;
            public const UInt32 RESET        =    0x80000     ;
            public const UInt32 TOP_DOWN     =   0x100000     ;
            public const UInt32 WRITE_WATCH  =   0x200000     ;
            public const UInt32 PHYSICAL     =   0x400000     ;
            public const UInt32 LARGE_PAGES  = 0x20000000     ;
            public const UInt32 FOURMB_PAGES = 0x80000000     ;
        }
    
        [Flags]
        public enum EFileAccess : uint
        {
            GenericRead = 0x80000000,
            GenericWrite = 0x40000000,
            GenericExecute = 0x20000000,
            GenericAll = 0x10000000,
        }
    
        [Flags]
        public enum EFileShare : uint
        {
            None = 0x00000000,
            Read = 0x00000001,
            Write = 0x00000002,
            Delete = 0x00000004,
        }
    
        public enum ECreationDisposition : uint
        {
            New = 1,
            CreateAlways = 2,
            OpenExisting = 3,
            OpenAlways = 4,
            TruncateExisting = 5,
        }
    
        [Flags]
        public enum EFileAttributes : uint
        {
            Readonly = 0x00000001,
            Hidden = 0x00000002,
            System = 0x00000004,
            Directory = 0x00000010,
            Archive = 0x00000020,
            Device = 0x00000040,
            Normal = 0x00000080,
            Temporary = 0x00000100,
            SparseFile = 0x00000200,
            ReparsePoint = 0x00000400,
            Compressed = 0x00000800,
            Offline= 0x00001000,
            NotContentIndexed = 0x00002000,
            Encrypted = 0x00004000,
            Write_Through = 0x80000000,
            Overlapped = 0x40000000,
            NoBuffering = 0x20000000,
            RandomAccess = 0x10000000,
            SequentialScan = 0x08000000,
            DeleteOnClose = 0x04000000,
            BackupSemantics = 0x02000000,
            PosixSemantics = 0x01000000,
            OpenReparsePoint = 0x00200000,
            OpenNoRecall = 0x00100000,
            FirstPipeInstance = 0x00080000
        }
    
    
    
    
    //-----------------------------------------------------------------------------
    // Functions
    
        internal class Kernel32
        {
            [DllImport("kernel32.dll")]
            public static extern void GetSystemInfo(
                out SYSTEM_INFO lpSystemInfo );
    
    
            [ DllImport( "Kernel32.dll" ) ]
            public static extern bool GetFileInformationByHandle
            (
                IntPtr hFile,
                out BY_HANDLE_FILE_INFORMATION lpFileInformation
            );
    
            [ DllImport( "kernel32.dll", SetLastError = true ) ]
            public static extern IntPtr CreateFile(
                string lpFileName,
                EFileAccess dwDesiredAccess,
                EFileShare dwShareMode,
                IntPtr lpSecurityAttributes,
                ECreationDisposition dwCreationDisposition,
                EFileAttributes dwFlagsAndAttributes,
                IntPtr hTemplateFile );
    
    
            [ DllImport( "Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode ) ]
            public static extern bool CreateHardLink
            (
                string FileName,
                string ExistingFileName,
                IntPtr lpSecurityAttributes
            );
    
            [ DllImport( "Kernel32.dll" ) ]
            public static extern bool Beep
            (
                UInt32 frequency,
                UInt32 duration
            );
    
            [ DllImport( "Kernel32.dll", SetLastError = true ) ]
            public static extern IntPtr OpenProcess(
                uint dwDesiredAccess,
                bool bInheritHandle,
                uint dwProcessId );
    
            [DllImport( "kernel32.dll", SetLastError = true ) ]
            public static extern IntPtr VirtualAllocEx(
                IntPtr hProcess,
                IntPtr lpAddress,
                UIntPtr dwSize,
                uint flAllocationType,
                uint flProtect);
    
            [DllImport("kernel32.dll")]
            public static extern bool ReadProcessMemory(
                IntPtr hProcess,
                IntPtr lpBaseAddress,
                IntPtr lpBuffer,
                UIntPtr nSize,
                IntPtr lpNumberOfBytesRead );
    
            [DllImport("kernel32.dll")]
            public static extern bool VirtualFreeEx(
                IntPtr hProcess,
                IntPtr lpAddress,
                UIntPtr dwSize,
                UInt32 dwFreeType );
    
            [DllImport("kernel32.dll")]
            public static extern bool GlobalMemoryStatusEx(
                MEMORYSTATUSEX buffer );
    
    
            [ DllImport( "kernel32.dll", SetLastError = true ) ]
            public static extern bool CloseHandle(
                IntPtr hObject );
    
        }
    
    //-----------------------------------------------------------------------------
    
    }
    

    User32.cs
    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);
    
    
    
    
    
        }
    }
    

    最佳答案

    我在32bit上检查了应用程序,然后看到了dwData != 0
    这有助于我理解问题出在64位上。

    我将public UInt32 dwData;替换为public 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);
      }
    

    最终结果:
    c# - 如何获取具有系统托盘图标的进程-LMLPHP

    该解决方案找不到与隐藏的系统任务栏图标相关联的进程,这是我需要研究的新问题:)。

    新的引用资料帮助我找到了该解决方案的主意:
    http://www.codeproject.com/Articles/10807/Shell-Tray-Info-Arrange-your-system-tray-icons

    这是一个名为“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;
    }
    

    关于c# - 如何获取具有系统托盘图标的进程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33652756/

    10-10 07:55