0

EnumWindows抓取EnumChildWindows许多许多窗口句柄。我只想要每个正在运行的进程的最高值。他们中的很多人从内部返回 0 Process.GetProcesses(),这是怎么回事?

我四处浏览并尝试了process.Refresh();,但没有好的结果。另请阅读其他文章。您如何MainWindowHandle正确抓取所有流程?

再说一遍:EnumWindows不仅获取主进程句柄,它还为每个进程获取许多句柄。

using System.Diagnostics;

Process[] p1 = Process.GetProcesses();
foreach (Process t in p1)
{
    listBox3.Items.Add(t.ProcessName + ": " + t.MainWindowHandle.ToString());
}
4

2 回答 2

3

您如何找到哪个窗口需要进程所有权?

这是一个误解,肯定是你被卡住的原因。窗口不拥有进程,反之亦然。更巧妙的是,一个线程拥有一个窗口。一个进程拥有一个线程。

当您使用 Process.GetProcesses() 时,您将枚举许多根本没有任何窗口的进程。像机器上运行的所有服务一样,拥有数十个服务并不罕见。您可以使用任务管理器在“进程”选项卡中查看它们,请务必单击显示所有用户拥有的进程的选项。SysInternals 的 Process Explorer 也是一个非常好的工具,可以查看正在运行的内容。

所以不要对 Process.MainWindowHandle 返回 IntPtr.Zero 感到惊讶。还要记住,这是一个猜测。一个进程可以轻松拥有多个顶级窗口。其中哪一个是“主”窗口并不总是很明显。Process 类使用一个简单的规则,它假定它找到的一个没有所有者且可见的顶级窗口是主窗口。

要可靠地获取进程的顶级窗口,您必须首先枚举进程中的线程。使用 Process.Threads 很容易做到。然后对于每个线程,您通过调用EnumThreadWindows()来迭代它拥有的窗口。与 EnumWindows() 完全相同的想法,但仅限于特定线程并且没有 firehose 问题,并且由于在迭代时创建了一个新窗口而导致它崩溃的可能性更低。您将获得线程拥有的顶级窗口,您想要什么,枚举每个顶级窗口拥有的子窗口需要 EnumChildWindows()。

一些值得注意的坏消息:请注意,需要进行一些过滤才能获得不错的结果。一个线程通常拥有一个根本不可见的窗口。通常用于处理线程间通信,尤其是使用 COM 的代码。因此,您可能还想调用 IsWindowVisible()。并始终检查这些 pinvoked 函数的错误,当您的程序未以管理员权限运行和/或未提升 UAC 时,故障很常见。始终根据您从 Spy++ 实用程序中看到的内容仔细检查您的结果。

于 2013-03-16T12:05:47.633 回答
0

如果您阅读MainWindowHandle的文档,您将看到以下注释:

如果关联进程没有主窗口,则 MainWindowHandle 值为零。对于已隐藏的进程,即在任务栏中不可见的进程,该值也为零。这可能是在任务栏最右侧的通知区域中显示为图标的进程。

请记住,它对应于最顶层窗口的句柄,它并不是真正的“主窗口句柄”,在这种情况下您最好使用手动枚举。

于 2013-03-16T11:14:36.343 回答