从Window Handle获取Window实例

时间:2011-02-25 11:02:19

标签: c# .net wpf

我可以使用以下代码从运行的应用程序中获取Window句柄。

foreach (ProcessModule module in process.Modules)
{
  if (module.ModuleName.Contains("PresentationFramework.dll") || module.ModuleName.Contains("PresentationFramework.ni.dll"))
  {
    IntPtr window = process.MainWindowHandle;
  }
}

但是我想从这个处理程序中获取Window实例。有可能吗?

请快点提问?

2 个答案:

答案 0 :(得分:11)

尝试以下方法:

IntPtr handle = process.MainWindowHandle;

HwndSource hwndSource = HwndSource.FromHwnd(handle);

Window = hwndSource.RootVisual as Window;

<强>更新

但这只能在同一个AppDomain中运行,否则就意味着你可以在不同的AppDomains甚至进程之间共享一个对象,这显然是不可能的。

答案 1 :(得分:7)

在WPF应用程序(或WinForms)中,有两个“对象”(即包含信息的内存块)到“窗口”:

  1. 系统窗口对象。
  2. “包装”系统对象的托管对象。
  3. 通过窗口句柄(非托管代码中的HWND类型,托管代码中的IntPtr)提供对系统窗口对象的访问。给定一个已经获得的窗口句柄,您可以使用Window API methods操作该窗口。你可以使用p / invoke。

    禁止访问驻留在进程堆中的托管对象(如果是托管进程,则访问AppDomain)。该存储器受到其他进程(1)的“保护”。

    在进程(或AppDomains)之间共享对象的唯一方法是通过编组,这是两个进程的合作努力。在访问另一个进程中的窗口时,这甚至适用于许多Win32 API方法。如果没有自定义编组,并非所有访问都可以。

    请注意,与WinForms不同,WPF(通常)不会将系统窗口用于控件。如果您的目标是操纵另一个WPF进程/域中的可视化树,那么除非该进程提供某种自动化接口,否则您只是运气不好。

    (1)虽然可以读取另一个进程的原始内存,但托管堆上的对象是移动目标。即使你能以某种方式暂停该过程的垃圾收集线程,人们也永远都找不到它们。