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

时间:2008-09-17 01:54:53

标签: c# .net windows user-interface

一种特殊情况问题:

  • 我使用System.Diagnostics.Process.Start(..)
  • 开始了一个流程
  • 此过程会打开一个闪屏 - 此闪屏将成为主窗口。
  • 启动画面关闭,显示“真实”用户界面。主窗口(启动画面)现在无效。
  • 我仍然有Process对象,我可以查询它的句柄,模块等。但是主窗口句柄现在无效。

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

我在网上看过,但我承认我没有看一个多小时。看起来应该有些微不足道: - (

9 个答案:

答案 0 :(得分:10)

如果您不介意使用Windows API,可以使用EnumWindowsProc,并使用GetWindowThreadProcessId检查出现的每个句柄(以查看它在您的过程中),以及然后可以IsWindowVisibleGetWindowCaptionGetWindowTextLength来确定您的流程中哪个hWnd是您想要的。

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

答案 1 :(得分:7)

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

为此,您需要使用FindWindowEx

答案 2 :(得分:3)

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

N.B:当然这需要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());
}

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

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

最后,我不得不说我不是Win32的专家,可能会有更好的解决方案。

答案 6 :(得分:1)

使用Process.GetProcessById(proc.Id); proc是你的闪屏。 适合我。

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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