Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET(C#):在只有进程句柄或PID的情况下获取子窗口?_C#_.net_Windows_User Interface - Fatal编程技术网

.NET(C#):在只有进程句柄或PID的情况下获取子窗口?

.NET(C#):在只有进程句柄或PID的情况下获取子窗口?,c#,.net,windows,user-interface,C#,.net,Windows,User Interface,这是一种特殊情况问题: 我使用System.Diagnostics.process.start(..)启动流程 该过程将打开一个启动屏幕--此启动屏幕将成为主窗口 启动屏幕关闭,显示“真实”用户界面。主窗口(启动屏幕)现在无效 我仍然拥有Process对象,可以查询其句柄、模块等,但主窗口句柄现在无效 此时,我需要获取流程的UI(或UI句柄)。假设我不能改变流程的行为来让这变得更容易(或更理智) 我在网上到处找过,但我承认我找了不到一个多小时。看起来应该有点琐碎:-(如果您知道窗口的标题,可

这是一种特殊情况问题:

  • 我使用
    System.Diagnostics.process.start(..)启动流程
  • 该过程将打开一个启动屏幕--此启动屏幕将成为主窗口
  • 启动屏幕关闭,显示“真实”用户界面。主窗口(启动屏幕)现在无效
  • 我仍然拥有Process对象,可以查询其句柄、模块等,但主窗口句柄现在无效
此时,我需要获取流程的UI(或UI句柄)。假设我不能改变流程的行为来让这变得更容易(或更理智)


我在网上到处找过,但我承认我找了不到一个多小时。看起来应该有点琐碎:-(

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


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

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


为此,您需要使用

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


不过,如果您以前没有使用过这些函数,那么这种方法将非常痛苦,因此希望有一种更简单的方法。

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


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

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

使用Process.GetProcessById(proc.Id);其中proc是您的初始屏幕。 对我有用

现在,您如何在System.Windows.Forms中获取主窗口属性,以便使用win32以w/o方式为其提供焦点?
毕竟.net应该是一个一站式的解决方案,不是吗?

在代码的某个地方,“真正的”主窗口已创建。此时您只需保存窗口句柄,然后在启动屏幕关闭后,您就可以将Application.MainWindow设置为真实窗口。

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

谢谢您的回答。多亏了您,我找到了如何知道流程是否在前面:

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

我发现,这是一个比FindWindowEx更健壮的解决方案,尽管设置起来更困难。当目标应用程序的多个实例运行时,FindWindowEx将很困难。