.NET(C#):只有进程句柄或者PID时才获得子窗口?
一种特殊情况的问题:
- 我从
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()); }