【问题标题】:Calling C# BHO methods from Javascript从 Javascript 调用 C# BHO 方法
【发布时间】:2012-03-06 11:23:29
【问题描述】:

我试图弄清楚如何从页面中的 Javascript 调用我的 BHO 对象中的 C# 方法。我发现了很多关于如何在 C++/ATL/Com 中执行此操作的页面,例如:

Browser Helper Objects and Scripts Options

Calling BHO method from Javascript?

我尝试在 C# 中正确实现它,但我无法让它工作,这可能是由于我没有完全理解的一些明显的 COM 问题。

我正在使用 C# 4.0。

以下是代码的相关部分:

using SHDocVw;
using mshtml;
using System.Runtime.InteropServices;

[ComVisible(true),
 Guid("300736C4-DCDA-4DB0-90AD-4510A12EBBC6"),
 ClassInterface(ClassInterfaceType.None),
 ProgId("My Extension")]
public class BrowserHelperObject : IObjectWithSite
{
    const int DISPATCH_PROPERTYPUT = 4;
    const int FDEX_NAME_ENSURE = 2;
    const uint LOCALE_USER_DEFAULT = 0x0400;

    WebBrowser browser;

    ...
    public void OnDocumentComplete(dynamic frame, ref dynamic url)
    {
        ...
        var window = browser.Document.parentWindow;

        int pid = 0;
        window.GetDispId("myExtension", FDEX_NAME_ENSURE, ref pid);

        System.Runtime.InteropServices.ComTypes.DISPPARAMS dispParms = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
        dispParms.cArgs = 1;
        dispParms.cNamedArgs = 0;
        dispParms.rgvarg = ???;
        dispParms.rgdispidNamedArgs = IntPtr.Zero;
        System.Runtime.InteropServices.ComTypes.EXCEPINFO einfo = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
        window.Invoke(pid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, ref dispParms, this, ref einfo);            
        ...
    }

【问题讨论】:

    标签: c# internet-explorer c#-4.0 com bho


    【解决方案1】:

    我不想回答我自己的问题,但我真的觉得社区应该知道答案,因为 C# 4.0 简短、简单且美观,而且似乎很多人都有这个问题。

    确保正确公开浏览器帮助器对象:

    [ComVisible(true),
     Guid("DA8EA345-02AE-434E-82E9-448E3DB7629E"),
     ClassInterface(ClassInterfaceType.None), ProgId("MyExtension"),
     ComDefaultInterface(typeof(IExtension))]
    public class BrowserHelperObject : IObjectWithSite, IExtension
    {
        ...
        public int Foo(string s) { ... }
        ...
        public void OnDocumentComplete(dynamic frame, ref dynamic url)
        {
            ...
            dynamic window = browser.Document.parentWindow;
            IExpando windowEx = (IExpando)window;
            windowEx.AddProperty("myExtension");
            window.myExtension = this;
            ...
        }
        ...
    }
    

    您需要为您的扩展定义一个定义:

    [ComVisible(true),
     Guid("4C1D2E51-018B-4A7C-8A07-618452573E42"),
     InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IExtension
    {
        [DispId(1)]
        int Foo(string s);
        ...
    }
    

    您可以在 javascript 中访问您的浏览器帮助对象:

    var result = window.myExtension.Foo("bar");
    

    或者只是

    var result = myExtension.Foo("bar");
    

    就是这样。别再用头撞墙了,去庆祝吧!

    【讨论】:

    • 不要后悔回答自己的问题。因为,i)人们寻找答案而不是回答的人,ii)您发布了问题并且您能够回答意味着你已经努力了..这真的是一件好事..恭喜....
    • 嗨定点。你能发布一个完整的工作原型吗?我试图准确地重现这个并且我的 window.myExtension 仍然是“未定义”我用我的完整来源发布了这个问题here
    • 如果它不适合你试试这个:浏览器对象需要是'IWebBrowser'而不是'IWebBrowser2'的实例
    • 可能您的实现类中没有包含 ComDefaultInterface(typeof(IExtension)),这就是它不起作用的原因
    • 在我的情况下,IExtension 的 GUID 不同。我使用C:\>reg query HKLM /s /f IExtension /d /e /c 来获得像HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{B05651CD-9B10-425E-B616-1FCD828DB3B1} 这样的输出,并且guid 在大括号中。
    【解决方案2】:

    另外,添加属性后,你需要确保释放 window 和 windowEx 的 COM 引用

    【讨论】:

    • 能否详细说明一下。
    猜你喜欢
    • 2012-07-21
    • 2012-02-07
    • 2013-02-10
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2014-03-22
    相关资源
    最近更新 更多