gpt4 book ai didi

c# - 如何获取具有系统托盘图标的进程

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:01:10 59 4
gpt4 key购买 nike

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

  1. http://www.raymond.cc/blog/find-out-what-program-are-running-at-windows-system-tray/

  2. https://superuser.com/questions/708674/how-to-find-out-what-process-a-system-tray-icon-corresponds-to

  3. Which Windows process is displaying a given taskbar system tray icon?

  4. https://social.msdn.microsoft.com/Forums/vstudio/en-US/53e27f60-37af-406f-bbdc-45db2bd3dee6/how-to-find-a-system-tray-process

  5. 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

  6. http://www.codeproject.com/Articles/10497/A-tool-to-order-the-window-buttons-in-your-taskbar

  7. Get ToolTip Text from Icon in System Tray

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

1我们有一个我想要的例子。

我想要有系统托盘图标的进程列表:
enter image description here名为“AnVir 任务管理器”的应用程序示例

使用来自链接 6 的代码我成功地遍历了系统托盘按钮并查看了每个按钮的文本:
enter image description here

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

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

代码:

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);





}
}

最佳答案

我检查了 32 位的应用程序,我看到 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);
}

最终结果:
enter image description here

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

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

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

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/

59 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com