C# 获取进程的所有窗口句柄
使用Microsoft Spy++,我可以看到以下属于某个进程的窗口: 进程XYZ窗口句柄,以树的形式显示,就像Spy++给我的一样:C# 获取进程的所有窗口句柄,c#,.net,process,window-handles,C#,.net,Process,Window Handles,使用Microsoft Spy++,我可以看到以下属于某个进程的窗口: 进程XYZ窗口句柄,以树的形式显示,就像Spy++给我的一样: A B C D E F G H I J K 我可以得到进程,MainWindowHandle属性指向窗口F的句柄。如果我使用枚举子窗口,我可以得到G到K的窗口句柄列表,但是我不知道如何找到从A到D的窗口句柄。如何枚举不是由Process对象的MainWindowHandle指定的句柄的子窗口 要枚举,我正在使用win
A
B
C
D
E
F
G
H
I
J
K
我可以得到进程,MainWindowHandle属性指向窗口F的句柄。如果我使用枚举子窗口,我可以得到G到K的窗口句柄列表,但是我不知道如何找到从A到D的窗口句柄。如何枚举不是由Process对象的MainWindowHandle指定的句柄的子窗口
要枚举,我正在使用win32调用:
[System.Runtime.InteropServices.DllImport(strUSER32DLL)]
public static extern int EnumChildWindows(IntPtr hWnd, WindowCallBack pEnumWindowCallback, int iLParam);
将
IntPtr.Zero
作为hWnd
传递以获取系统中的每个根窗口句柄
然后,您可以通过调用来检查windows的所有者进程。您可以使用它来获取每个顶级窗口,然后根据这些窗口筛选结果。对于仍在疑惑的所有人,以下是答案:
List<IntPtr> GetRootWindowsOfProcess(int pid)
{
List<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero);
List<IntPtr> dsProcRootWindows = new List<IntPtr>();
foreach (IntPtr hWnd in rootWindows)
{
uint lpdwProcessId;
WindowsInterop.User32.GetWindowThreadProcessId(hWnd, out lpdwProcessId);
if (lpdwProcessId == pid)
dsProcRootWindows.Add(hWnd);
}
return dsProcRootWindows;
}
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
WindowsInterop.Win32Callback childProc = new WindowsInterop.Win32Callback(EnumWindow);
WindowsInterop.User32.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
对于WindowsInterop.User32:
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
现在,只需通过GetRootWindowsOfProcess获取每个根窗口,并通过GetChildWindows获取它们的子窗口。过去有一个C类,在关闭GotDotNet站点之前,它将所有这些都很好地封装在了GotDotNet站点上。再也找不到了,但它就在外面某个地方……这是唯一的办法吗?我要试试这个。我想知道这个操作会花费多少时间…不仅仅是您的示例,GetChildWindows在传入Process.GetCurrentProcess().MainWindowHandle时根本不起作用。我启动了一个子窗口(不管是不是modally),调用GetChildWindows,EnumWindow回调根本就不会启动。你是说操作系统?Win8.WIndows 8就是问题所在。不,只是在Win上尝试过;同样的事情。这是微软一直擅长的一件事;这些API调用在OSs上的工作原理是一样的。我尝试了Win8,但没有成功。他们改变了Win8中屏幕和句柄的工作方式。但是对于Win7,它对我来说是有效的(同样的笔记本——在这些问题之后我降低了它的等级)。因此,它在Win7上不起作用肯定还有另一个原因。这不是操作系统。
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);