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

一种特殊情况下的问题:

  • 我用System.Diagnostics.Process.Start(..)启动一个进程
  • 这个过程打开一个闪屏 – 这个闪屏成为主窗口。
  • 启animation面closures,并显示“真实”的用户界面。 主窗口(启animation面)现在无效。
  • 我仍然有过程对象,我可以查询它的句柄,模块等,但主窗口句柄现在是无效的。

我需要获取进程的UI(或UI处理)。 假设我不能改变这个过程的行为,以使这个更容易(或更安全)。

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

Solutions Collecting From Web of ".NET(C#):当你只有一个进程句柄或PID时获取子窗口?"

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

虽然如果在这种方法之前你还没有使用过这些功能,那么这种方法将是一个很好的解决方法,所以希望有一个更简单的方法。

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

为此,您将需要使用FindWindowEx

谢谢您的回答。 感谢你在这里,我想出了如何知道一个过程的主窗口是否在前面:

注意:当然这需要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()); } 

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

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

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

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

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

使用Process.GetProcessById(proc.Id); proc是你的启动画面。 为我工作。

现在,你如何获得在System.Windows.Forms的主要窗口属性使它无焦点使用win32? 毕竟.net应该是一站式的解决方案 – 不是吗?

在代码的某个地方,“真正的”主窗口被创建。 您可以保存当时的窗口句柄,然后在启动画面关闭后,您可以将Application.MainWindow设置为真正的窗口。

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