答案 0 :(得分:74)
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn,
IntPtr lParam);
static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processId)
{
var handles = new List<IntPtr>();
foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
EnumThreadWindows(thread.Id,
(hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
return handles;
}
和样本用法:
private const uint WM_GETTEXT = 0x000D;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam,
StringBuilder lParam);
[STAThread]
static void Main(string[] args)
{
foreach (var handle in EnumerateProcessWindowHandles(
Process.GetProcessesByName("explorer").First().Id))
{
StringBuilder message = new StringBuilder(1000);
SendMessage(handle, WM_GETTEXT, message.Capacity, message);
Console.WriteLine(message);
}
}
答案 1 :(得分:15)
使用Win32 API EnumWindows(如果您想要子窗口EnumChildWindows)),或者您可以使用EnumThreadWindows 。
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData);
然后使用Win32 API GetWindowThreadProcessId
检查每个窗口所属的进程[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int GetWindowThreadProcessId(HandleRef handle, out int processId);
答案 2 :(得分:3)
古老的线程,但它让我开始了,所以这里是一个小的实用函数,它将找到一个匹配lambda(Predicate)的子窗口。易于更改以返回列表。在谓词中处理多个条件。
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
/// <summary>
/// Find a child window that matches a set of conditions specified as a Predicate that receives hWnd. Returns IntPtr.Zero
/// if the target window not found. Typical search criteria would be some combination of window attributes such as
/// ClassName, Title, etc., all of which can be obtained using API functions you will find on pinvoke.net
/// </summary>
/// <remarks>
/// <para>Example: Find a window with specific title (use Regex.IsMatch for more sophisticated search)</para>
/// <code lang="C#"><![CDATA[var foundHandle = Win32.FindWindow(IntPtr.Zero, ptr => Win32.GetWindowText(ptr) == "Dashboard");]]></code>
/// </remarks>
/// <param name="parentHandle">Handle to window at the start of the chain. Passing IntPtr.Zero gives you the top level
/// window for the current process. To get windows for other processes, do something similar for the FindWindow
/// API.</param>
/// <param name="target">Predicate that takes an hWnd as an IntPtr parameter, and returns True if the window matches. The
/// first match is returned, and no further windows are scanned.</param>
/// <returns> hWnd of the first found window, or IntPtr.Zero on failure </returns>
public static IntPtr FindWindow(IntPtr parentHandle, Predicate<IntPtr> target) {
var result = IntPtr.Zero;
if (parentHandle == IntPtr.Zero)
parentHandle = Process.GetCurrentProcess().MainWindowHandle;
EnumChildWindows(parentHandle, (hwnd, param) => {
if (target(hwnd)) {
result = hwnd;
return false;
}
return true;
}, IntPtr.Zero);
return result;
}
实施例
var foundHandle = Win32.FindWindow(IntPtr.Zero, ptr => Win32.GetWindowText(ptr) == "Dashboard");
答案 3 :(得分:-2)
过了一会儿,我发现了一种简单而简短的方法:
您需要:&#34; 使用System.Diagnostics; &#34;
[DllImport("kernel32.dll", SetLastError = true)] // Optional
[return: MarshalAs(UnmanagedType.Bool)] // Optional
private void button1_Click(object sender, EventArgs e)
{
AllocConsole(); // Easy to read // Optional
Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
if (!string.IsNullOrEmpty(process.MainWindowTitle))
{
Console.WriteLine("Process: {0} ID: {1} Window title: {2}",
process.ProcessName, process.Id, process.MainWindowTitle);
}
}
}