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