为什么Control.FromHandle(IntPtr)在一个挂钩进程中返回null并返回“Form”的有效对象? 在另一个钩过程中?

我面临的问题是从一些钩子进程中取出所有控件。 我的SpyDll成功启动了钩子流程,但当我查看声明时

控制控件= Control.FromHandle(MainWindowHandle),它将null返回到控制对象,其中“MainWindowhandle”只是该挂钩进程的本机主窗口句柄,在启动该进程后,您始终从.NET“Process”类中获取该处理。

但严重的是,在其他一些与C#.NET应用程序相同的钩子化进程中,它会返回Main“WinForm”的有效对象。

那么为什么它不适用于上述情况呢? 是否有正确使用“MainWindowHandle”的例外情况。 在我的例子中,两者都是用C#编程的单独的.NET托管进程。 在创建该流程时,是否需要专门维护任何流程配置?

关心乌斯曼

1.)请记住,可能有多个appdomains,你只能在当前进程中获取当前appdomain的控件对象。 此外,你必须使用正确的ruuntime-version afaik,但我不确定。

2.)为什么你还需要控制句柄,直接使用本机句柄更方便,甚至可以使用其他进程中的本机函数,不需要dll注入。 如果您确实需要托管控件对象, 请查看Application.OpenForms集合而不是该句柄搜索!

使用WinForms创建控件/表单时,WinForm代码将自动保留一个将本机窗口句柄映射到C#实例的条目。 当控制/表单被销毁时,该条目将被删除。 因此,调用Control.FromChildHandle所做的就是搜索条目列表以查看它是否具有匹配的本机句柄,如果是,则返回关联的C#实例。

因此,您只能获取从WinForms本身创建的Control / Form实例的C#条目。 附加到另一个进程的本机窗口和本机控件永远不会返回一个条目。 这就是为什么在使用WinForms创建窗口的C#应用​​程序中使用C#应用程序时,为什么不能为您工作,也永远不会有效。

这是因为您调用的函数“Control.FromHandle”使用哈希表从其句柄中查找控件实例。 因此,当您为没有控件实例的HWND调用此方法时,您将获得null。

要使用HWND,您应该通过PInvoke调用使用Win32 Messaging API 。 例如,您可以使用SendMessage发送WM_GETTEXT消息来查询窗口的文本。 对于其中一些消息, Win32 Windowing API中有各种包装器,如GetWindowText ,它包含上述消息。

您是否考虑过使用Control.FromChildHandle ? 它将搜索控制链,直到找到与该句柄相关联的控件。

在你的第一种情况下,它可能不是一个直接的后代。

对于任何给定的AppDomain,T类型的非静态成员存在于实体(T的实例)中。 类型ot T的静态成员存在于另一个单独的实体(类型T本身)中。 因此,一个AppDomain中的T类型或实例与另一个AppDomain中的T的类型或实例不同。 这意味着Control.FromHandle仅在返回的实例与调用方法位于同一AppDomain中时才有意义,否则它必须返回null。

要使用其他AppDomain,您需要一些COM样式编码,类似于(伪代码):

 runtimes = IClrMetaHost.EnumerateLoadedRuntimes(processHandle); host = runtime[0].GetInterface( ICorRuntimeHost ); appdomains = host.EnumDomains(); appdomains[0].CallBack( () => dosomething(); );