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

时间:2020-03-05 18:57:41  来源:igfitidea点击:

一种特殊情况的问题:

  • 我从System.Diagnostics.Process.Start(..)开始一个过程
  • 该过程将打开一个初始屏幕-此初始屏幕成为主窗口。
  • 初始屏幕关闭,并显示"真实" UI。现在,主窗口(启动屏幕)无效。
  • 我仍然有Process对象,可以查询其句柄,模块等。但是主窗口句柄现在无效。

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

我在网上环顾四周,但我承认我待了一个多小时。似乎应该有点琐碎:-(

解决方案

回答

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

我们可以在pinvoke.net上找到签名

回答

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

为此,我们将需要使用FindWindowEx

回答

如果我们不介意使用Windows API,则可以使用" EnumWindowsProc",并使用" GetWindowThreadProcessId"(检查它是否在进程中),然后检查" IsWindowVisible",检查每个出现的句柄。使用GetWindowCaption和GetWindowTextLength来确定进程中的哪个hWnd是我们想要的。

尽管如果我们在使用该方法之前没有使用过这些功能会很痛苦,那么希望有一种更简单的方法。

回答

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

最后,我不得不说我不是Win32方面的专家,因此可能会为情况提供更好的解决方案。

回答

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

回答

使用Process.GetProcessById(proc.Id); proc是初始屏幕。
为我工作。

现在,如何使用Win32进入System.Windows.Forms的主窗口属性以使其不带焦点?
毕竟.net应该是一站式解决方案,不是吗?

回答

在代码中的某个地方,创建了"真实"主窗口。我们可以只保存当时的窗口句柄,然后在初始屏幕关闭后将Application.MainWindow设置为真实窗口。

回答

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

回答

谢谢回答。感谢我们在这里的帮助,我弄清楚了如何知道进程的主窗口是否在前面:

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