从Javascript调用C#BHO方法

我正试图弄清楚如何在页面内的Javascript中调用我的BHO对象中的C#方法。 我在C ++ / ATL / Com中找到了很多关于如何做的页面,例如:

浏览器帮助程序对象和脚本选项

从Javascript调用BHO方法?

我试图在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#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"); 

而已。 别再撞到墙上去庆祝吧!

此外,添加属性后,您需要确保释放窗口和windowEx的COM引用