.NET (C#):只有进程句柄或 PID 时获取子窗口?

Posted

技术标签:

【中文标题】.NET (C#):只有进程句柄或 PID 时获取子窗口?【英文标题】:.NET (C#): Getting child windows when you only have a process handle or PID? 【发布时间】:2010-09-09 21:31:14 【问题描述】:

一种特殊情况的问题:

我用System.Diagnostics.Process.Start(..) 开始一个进程 该进程打开一个初始屏幕 -- 此初始屏幕成为主窗口。 启动屏幕关闭并显示“真实”用户界面。主窗口(启动画面)现在无效。 我还有Process对象,可以查询它的句柄、模块等,但是主窗口句柄现在无效了。

此时我需要获取进程的 UI(或 UI 句柄)。假设我无法更改流程的行为以使其更容易(或更理智)。

我在网上浏览了一遍,但我承认我没有找一个多小时。似乎它应该有点微不足道:-(

【问题讨论】:

【参考方案1】:

如果您不介意使用 Windows API,您可以使用 EnumWindowsProc,并检查使用 GetWindowThreadProcessId 出现的每个句柄(以查看它是否在您的进程中),然后可能是 @987654325 @、GetWindowCaptionGetWindowTextLength 来确定您的进程中的哪个 hWnd 是您想要的。

虽然如果你之前没有使用过这些功能,那么这种方法会很痛苦,所以希望有一种更简单的方法。

【讨论】:

我发现这是一个比 FindWindowEx 更强大的解决方案,尽管它更难设置。当目标应用程序的多个实例正在运行时,FindWindowEx 会遇到困难。【参考方案2】:

@ageektrapped 在正确的轨道上,但是FindWindow 不会搜索子窗口。

为此,您需要使用FindWindowEx

【讨论】:

【参考方案3】:

感谢您的回答。多亏了你,我想出了如何知道进程的主窗口是否在前面:

注意:当然这需要 System.Diagnostic 和 System.Runtime.Interrop

public bool IsWindowActive(Int32 PID)

  return IsWindowActive(Process.GetProcessById(PID));


[DllImport("user32.dll")]
private static extern
IntPtr GetForegroundWindow();

public bool IsWindowActive(Process proc)

  proc.Refresh();
  return proc.MainWindowHandle.Equals(GetForegroundWindow());

【讨论】:

【参考方案4】:

您可能会发现,如果您调用 .Refresh() 会获得新的***窗口。

【讨论】:

【参考方案5】:

如果您知道窗口的标题,则可以通过 P/Invoke 使用 Win32 调用 FindWindow。

您可以在 pinvoke.net 上找到签名 here

【讨论】:

【参考方案6】:

据我了解,您正在启动的进程的MainWindowHandle 属性无效。如果是这种情况,您可以使用 FindWindow 函数(来自 Win32 SDK)返回您需要的窗口句柄。您所需要的只是目标应用程序主窗口的类名。您可以使用 Spy++ 或 Winspector 获取它。您还需要使用GetWindowThreadProcessId 检查该窗口的进程ID,以确保您拥有正确的窗口。

最后,我不得不说我不是 Win32 方面的专家,对于你的情况可能有更好的解决方案。

【讨论】:

【参考方案7】:

使用 Process.GetProcessById(proc.Id); proc 是您的启动画面。 对我有用。

现在,如何使用 win32 访问 System.Windows.Forms 中的主窗口属性以使其获得焦点? 毕竟 .net 应该是一站式解决方案 - 不是吗?

【讨论】:

【参考方案8】:

在代码中的某处,创建了“真正的”主窗口。您可以在那时保存窗口句柄,然后在启动屏幕关闭后您可以将 Application.MainWindow 设置为真实窗口。

【讨论】:

【参考方案9】:

MainWindowHandle 属性在首次访问后被缓存,这就是为什么即使在句柄失效后您也看不到它发生变化的原因。 GregUzelac 的信息是正确的。调用 Proces.Refresh 将导致对 Process.MainWindowHandle 的下一次调用重新执行逻辑以查找新的主窗口句柄。 Michael 的逻辑也有效,因为新进程没有 MainWindowHandle 的缓存版本。

【讨论】:

以上是关于.NET (C#):只有进程句柄或 PID 时获取子窗口?的主要内容,如果未能解决你的问题,请参考以下文章

C# 根据进程ID获取进程主窗口句柄

如何从另一个 .NET 进程获取对象的句柄?

C# - 尝试获取进程句柄时访问被拒绝

vb.net中如何获得某个窗口的句柄

Delphi 我想获得进程句柄,怎么每次都变化

Delphi 我想获得进程句柄,怎么每次都变化