【问题标题】:how do you find what window(Handle) takes process ownership? And get the handle for that..?你如何找到哪个窗口(句柄)需要进程所有权?并得到那个句柄..?
【发布时间】:2013-03-16 10:41:21
【问题描述】:

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());
}

【问题讨论】:

标签: c# .net winapi process


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 你怎么知道 Process.MainWindowHandle 猜测进程创建的第一个顶级窗口是它的主窗口?我尝试查看 Reflector 中的代码。我看到回调函数调用了另一个内部辅助函数 IsMainWindow。那个调用 GetWindow 来检查 GW_OWNER 和 IsWindowVisible。我没有看到任何检查创建时间或顺序的东西——我什至不知道这样的事情是可能的。 (顺便说一句,这个答案的解释很好!)
【解决方案2】:

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

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

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

【讨论】:

  • 如何找到进程所有权的窗口?并得到那个句柄..?
猜你喜欢
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多