代码之家  ›  专栏  ›  技术社区  ›  Andrew Florko

WinForms:Form.FromHandle为加载到.net可执行文件中的代码的进程主窗体返回null

  •  1
  • Andrew Florko  · 技术社区  · 14 年前

    我有一个用.Net编写的遗留应用程序。没有可用的来源。它使用vb脚本通过事件处理扩展其内部逻辑。所以它是com和.net的混合体。

    我使用了SpyUI应用程序,观察到UI是用Windows窗体编写的。控件的标题为.Net样式,它看起来像windows窗体1(vc++和vb UI看起来完全不同)。

    我想通过实现主窗体的System.Windows.Forms.Form实例和修改控件树来扩展应用程序UI。

    所以我用vb脚本编写代码来创建我的com对象,比如:

    Set obj = CreateObject("MyUiExtender")
    obj.InjectIntoUi()
    

    我试图获取进程对象的主窗体句柄已加载到中,此代码可以工作:

    Process.GetCurrentProcess().MainWindowHandle; // a meaningfull value
    Process.GetCurrentProcess().MainWindowTitle; // the title of the application 
    

    到目前为止还不错,但以下操作不起作用->它返回空值

    var mainForm = Control.FromHandle(Process.GetCurrentProcess().MainWindowHandle)
    

    我的对象已加载到可执行文件中,我尝试获取同一进程的表单实例。我想这是一种应用程序边界问题。如果我的com对象通过

    t = Type.GetTypeFromProgID("MyUiExtender")
    dynamic c = Activator.CreateInstance(t)
    c.InjectIntoUi();
    

    我想使用vb脚本会以某种方式破坏应用程序边界。。。

    仍然可以将主应用程序窗体实例作为Windows.Forms.form类的实例获取吗?

    1 回复  |  直到 14 年前
        1
  •  1
  •   michalczerwinski    13 年前

    问题是Control.FromHandle只适用于当前进程。如果要获取另一个.Net进程的主窗体,则必须将代码注入其他进程。

    几乎没有办法做到这一点。最常见的方法是使用CreateRemoteThread将非托管dll加载到其他进程地址空间,然后加载.NET程序集。为了使它成为可能,你必须使用C++管理。

    如果你是初学者,我建议使用现有的图书馆。看看CodePlex的Hawkeye项目: http://hawkeye.codeplex.com/ 你可以在那里找到一个现成的图书馆。

    你也可以看看 http://smuxplugins.codeplex.com/ 这是.net代码注入的另一个例子。