从Window Handle获取Window实例

Jaw*_*har 13 .net c# wpf

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

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

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

有什么好主意吗?

Pav*_*kov 11

请尝试以下方法:

IntPtr handle = process.MainWindowHandle;

HwndSource hwndSource = HwndSource.FromHwnd(handle);

Window = hwndSource.RootVisual as Window;
Run Code Online (Sandbox Code Playgroud)

更新:

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

  • @Jawahar - 这是一个概念性问题,并非特定于.NET.您不能跨进程共享相同的对象.假设您从不同的进程获得了一个窗口的实例.现在问问自己,如果你改变这个窗口的某些属性(例如位置)会发生什么?如果有可能,那么任何程序都可以操纵任何其他程序的窗口...... (2认同)

Ter*_*ver 9

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

  1. 系统窗口对象.
  2. "包装"系统对象的托管对象.

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

禁止访问驻留在进程堆中的托管对象(或托管进程中的AppDomain).该存储器受到其他进程的"保护"(1).

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

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

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