internetexplorer-从Javascript调用C#BHO方法(仍然无法工作)
本文关键字:工作 Javascript 调用 C#BHO 方法 internetexplorer- | 更新日期: 2023-09-27 18:01:04
我准确地遵循了这个答案,反复阅读了所有谷歌搜索结果。不幸的是,大多数都只是参考答案的复制粘贴(包括"别再把头撞墙了,去庆祝吧!"(这句话对我不起作用……所以工作了半天,我真的要开始撞头了。。。
我的简单错误:javascript windows.myExtension对象"未定义",因此在其上调用Foo会引发错误。请参阅下面的完整来源。在javascript端似乎无法查看属性集。
更多信息:
- 我使用Debugger.Launch((语句来方便地调试我的扩展,并且断点被命中,所有BHO扩展函数都被正确地调用和运行
-
注释的备选方案(具有属性.SetProperty(也不起作用,出现相同错误:
console.log(window.myExtension(;//写"未定义",为什么?
-
使用VS 2010,Windows 7 x64,IE 9
请让我帮忙运行这个。。。Thx提前
简单的测试页面:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
console.log(window.myExtension); // Writes undefined why? It should be an object...
var result = window.myExtension.Foo("bar"); // Obviously throws and error if window.myExtension is undefined
</script>
<title></title>
</head>
<body>
</body>
</html>
BrowserHelperObject.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Expando;
using Microsoft.Win32;
using SHDocVw;
namespace IEExtensionTest
{
[ComVisible(true)]
[Guid("DA8EA345-02AE-434E-82E9-448E3DB7629E")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("MyExtension")]
[ComDefaultInterface(typeof(IExtension))]
public class BrowserHelperObject : IObjectWithSite, IExtension
{
private WebBrowser webBrowser;
public int Foo(string s)
{
return 0;
}
public void OnDocumentComplete(dynamic frame, ref dynamic url)
{
Debugger.Launch();
dynamic window = webBrowser.Document.parentWindow;
var windowEx = (IExpando)window;
windowEx.AddProperty("myExtension");
window.myExtension = this;
//var property = windowEx.AddProperty("MyExtension");
//property.SetValue(windowEx, this, null);
}
public static string BHOKEYNAME = "Software''Microsoft''Windows''CurrentVersion''Explorer''Browser Helper Objects";
[ComRegisterFunction]
public static void RegisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true);
if (registryKey == null)
registryKey = Registry.LocalMachine.CreateSubKey(BHOKEYNAME);
string guid = type.GUID.ToString("B");
RegistryKey ourKey = registryKey.OpenSubKey(guid);
if (ourKey == null)
ourKey = registryKey.CreateSubKey(guid);
ourKey.SetValue("Alright", 1);
registryKey.Close();
ourKey.Close();
}
[ComUnregisterFunction]
public static void UnregisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true);
string guid = type.GUID.ToString("B");
if (registryKey != null)
registryKey.DeleteSubKey(guid, false);
}
public int SetSite(object site)
{
if (site != null)
{
webBrowser = (WebBrowser)site;
webBrowser.DocumentComplete += OnDocumentComplete;
}
else
{
webBrowser.DocumentComplete -= OnDocumentComplete;
webBrowser = null;
}
return 0;
}
public int GetSite(ref Guid guid, out IntPtr ppvSite)
{
IntPtr punk = Marshal.GetIUnknownForObject(webBrowser);
int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
Marshal.Release(punk);
return hr;
}
}
IObjectWithSite.cs
using System;
using System.Runtime.InteropServices;
namespace IEExtensionTest
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")]
public interface IObjectWithSite
{
[PreserveSig]
int SetSite([MarshalAs(UnmanagedType.IUnknown)] object site);
[PreserveSig]
int GetSite(ref Guid guid, out IntPtr ppvSite);
}
}
IE扩展.cs
using System;
using System.Runtime.InteropServices;
namespace IEExtensionTest
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")]
public interface IObjectWithSite
{
[PreserveSig]
int SetSite([MarshalAs(UnmanagedType.IUnknown)] object site);
[PreserveSig]
int GetSite(ref Guid guid, out IntPtr ppvSite);
}
}
构建后步骤配置如下(并正确运行(:
"C:'Program Files (x86)'Microsoft SDKs'Windows'v7.0A'Bin'NETFX 4.0 Tools'gacutil.exe" /f /i "$(TargetDir)$(TargetFileName)"
"C:'Windows'Microsoft.NET'Framework'v4.0.30319'RegAsm.exe" /unregister "$(TargetDir)$(TargetFileName)"
"C:'Windows'Microsoft.NET'Framework'v4.0.30319'RegAsm.exe" "$(TargetDir)$(TargetFileName)"
我有一个破解的解决方案。它现在对我有效,所以我把它贴在这里。如果我遇到任何问题,我会更新这篇文章。
@Eli Gassert正确识别了问题。在SetSite
函数中,我们将向DocumentComplete
事件添加一个处理程序。因此,当我们处于$.ready()
时,它不会执行。
所以我所做的是将处理程序添加到BeforeScriptExecute事件中。这是我的BHO.cs 的相关部分
public int SetSite(object site)
{
this.site = site;
if(site != null)
{
webBrowser = (IWebBrowser2)site;
((DWebBrowserEvents2_Event)webBrowser).BeforeScriptExecute += S2_BeforeScriptExecute;
//((DWebBrowserEvents2_Event)webBrowser).DocumentComplete += S2_DocumentComplete;
}
else
{
((DWebBrowserEvents2_Event)webBrowser).BeforeScriptExecute -= S2_BeforeScriptExecute;
//((DWebBrowserEvents2_Event)webBrowser).DocumentComplete -= S2_DocumentComplete;
webBrowser = null;
}
return 0;
}
处理程序的签名不同,这里是处理程序的代码。这仍然在BHO.cs 中
private void S2_BeforeScriptExecute(object pDispWindow)
{
//if (pDisp != this.site) { return; }
dynamic window = webBrowser.Document.parentWindow;
IExpando windowEx = (IExpando)window;
windowEx.AddProperty("myprop");
window.myprop = this;
}
我只是粘贴了来自DocumentComplete
方法的代码,并在顶部注释掉了条件。
因此,我能够在jquery $.ready()
中看到myprop
。这已经解决了我眼前的问题,我正在继续我的代码。
不用说,我的插件只提供将从javascript调用的方法,不需要对文档内容做任何操作。
我还不知道pDispWindow
有什么用,不检查它是否为null会有什么影响,等等。
尝试使用窗口外部.myExtension((;在我记忆中,外部是保持你的形体的物体。此外,如果这不起作用,一定要先尝试简单的事情,然后反其道而行之。
这里有一个简单的表单应该对你有效:
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] // Note full trust.
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class BasicJSScriptableForm : Form
{
private void BasicJSScriptableForm _Load(object sender, EventArgs e){
this.WebBrowser1.Navigate("yourpage");
}
public string TestMethod(string input){
return string.Format("echo: {0}", input);
}
}
然后在页面中:
$(document).ready(function() {
alert(window.external.TestMethod("It will hopefully work."));
}