EnumWindows
和EnumChildWindows
抓住许多窗口句柄。我只是希望每个运行过程都是最顶层的。很多人从Process.GetProcesses()
内返回0,这是什么交易?
我浏览了周围并尝试了process.Refresh();
并没有取得好成绩。另请阅读其他文章。你如何正确地抓住所有进程MainWindowHandle
?
再次:EnumWindows
不仅获得主进程句柄,而是为每个进程抓取许多句柄。
using System.Diagnostics;
Process[] p1 = Process.GetProcesses();
foreach (Process t in p1)
{
listBox3.Items.Add(t.ProcessName + ": " + t.MainWindowHandle.ToString());
}
答案 0 :(得分:3)
如何找到需要进程所有权的窗口?
这是一种误解,当然是你被困的原因。一个窗口不拥有一个进程,反之亦然。更巧妙的是,线程拥有一个窗口。一个进程拥有一个线程。
当您使用Process.GetProcesses()时,您将枚举一个完全没有任何窗口的 lot 进程。就像在机器上运行的所有服务一样,拥有数十个这样的服务并不罕见。您可以使用任务管理器在“进程”选项卡中查看它们,确保单击显示所有用户拥有的进程的选项。 Sysinternals的' Process Explorer也是一个非常好的工具,可以查看正在运行的内容。
所以请不要惊讶于Process.MainWindowHandle返回IntPtr.Zero。并且还要记住它是 guess 。一个进程可以轻松拥有多个顶级窗口。其中哪一个是"主要"窗口并不总是显而易见的。 Process类使用一个简单的规则,它假定它找到的第一个顶层窗口没有所有者并且是可见的是主窗口。
要可靠地获取进程的顶级窗口,必须首先枚举进程中的线程。易于使用Process.Threads。然后,对于每个线程,通过pinvoking EnumThreadWindows()迭代它拥有的窗口。与EnumWindows()完全相同的想法,但仅限于特定的线程,没有firehose问题,并且由于在迭代时创建了一个新窗口,因此它分崩离析的可能性较低。您将获得该线程拥有的顶级窗口,您想要的是,枚举每个顶级窗口所拥有的子窗口需要EnumChildWindows()。
一些值得注意的坏消息:请注意,需要进行一些过滤以获得不错的结果。线程通常拥有一个根本看不到的窗口。通常用于处理线程间通信,对于使用COM的代码尤其常见。所以你可能也想要调用IsWindowVisible()。并且始终检查这些被激活的函数的错误,当您的程序没有以管理员权限运行和/或UAC未升级时,故障很常见。始终根据您从Spy ++实用程序中看到的内容仔细检查结果。
答案 1 :(得分:0)
如果您阅读MainWindowHandle的文档,则会看到以下注释:
如果关联的进程没有主窗口,则MainWindowHandle值为零。对于已隐藏的进程(即,任务栏中不可见的进程),该值也为零。对于在任务栏最右侧的通知区域中显示为图标的进程,可能就是这种情况。
请记住它对应于最顶层窗口的句柄,它不是真正的“主窗口句柄”,在这种情况下你可能最好使用手动枚举。