从Javascript调用C#BHO的方法(仍然没有工作) [英] Calling C# BHO methods from Javascript (still not working)

查看:1210
本文介绍了从Javascript调用C#BHO的方法(仍然没有工作)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我跟着这正是接听和看了又看所有谷歌发现。不幸的是他们中的大多都是简单地复制和参考答案的膏(包括停止撞你的头靠在墙上,去庆祝吧!')一句话,它并没有为我工作......因此,一个半天工作后,我真的要开始敲我的头...



我的简单的错误:
JavaScript的windows.myExtension对象未定义这样调用foo它会抛出错误。请参见下面的完整的源代码。它似乎属性集是不是在JavaScript端观看



一些详细信息:




  • 我用的是Debugger.Launch()语句方便的方法来调试我的延伸,断点被击中,所有的BHO扩展函数,正确调用并运行。

  • 注释的替代(用property.SetProperty)也不起作用,用了同样的错误:



    执行console.log(window.myExtension); //写未定义,为什么呢?


  • 使用VS 2010,Windows 7的64,IE 9




请让我来帮助运行提前这个...
THX



简单的测试页面:

 <!DOCTYPE HTML> 
< HTML和GT;
< HEAD>
<脚本类型=文/ JavaScript的>
的console.log(window.myExtension); //写不确定为什么呢?它应该是一个对象...
VAR的结果= window.myExtension.Foo(巴); //显然罚球和错误,如果window.myExtension未定义
< / SCRIPT>
<标题>< /标题>
< /头>
<身体GT;

< /身体GT;
< / HTML>



BrowserHelperObject.cs

 使用系统;使用System.Diagnostics程序
;使用System.Runtime.InteropServices
;
使用System.Runtime.InteropServices.Expando;

使用的Microsoft.Win32;

使用SHDOCVW;

命名空间IEExtensionTest
{
[标记有ComVisible特性(真)]
[的Guid(DA8EA345-02AE-434E-82E9-448E3DB7629E)]
[ ClassInterface(ClassInterfaceType.None)
[的ProgId(MyExtension)]
[ComDefaultInterface(typeof运算(IExtension))]
公共类BrowserHelperObject:接口IObjectWithSite,IExtension
{
私人web浏览器web浏览器;

公众诠释美孚(字符串s)
{
返回0;
}

公共无效OnDocumentComplete(动感相框,动态参考URL)
{
Debugger.Launch();
动态窗口= webBrowser.Document.parentWindow;
VAR windowEx =(IExpando)窗口;
windowEx.AddProperty(myExtension);
window.myExtension =这一点;
// VAR财产= windowEx.AddProperty(MyExtension);
//property.SetValue(windowEx,对此,NULL);
}


公共静态字符串BHOKEYNAME =Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser助手对象;

[ComRegisterFunction]
公共静态无效RegisterBHO(type类型)
{
的RegistryKey的RegistryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME,真);

如果(的RegistryKey == NULL)
的RegistryKey = Registry.LocalMachine.CreateSubKey(BHOKEYNAME);

字符串GUID = type.GUID.ToString(B);
的RegistryKey ourKey = registryKey.OpenSubKey(GUID);

如果(ourKey == NULL)
ourKey = registryKey.CreateSubKey(GUID);

ourKey.SetValue(好,1);
registryKey.Close();
ourKey.Close();
}

[ComUnregisterFunction]
公共静态无效UnregisterBHO(type类型)
{
的RegistryKey的RegistryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME,真) ;
字符串GUID = type.GUID.ToString(B);

如果(的RegistryKey!= NULL)
registryKey.DeleteSubKey(GUID,FALSE);
}

公众诠释SetSite(对象的网站)
{

如果(网站!= NULL)
{
web浏览器=(web浏览器)的网站;
webBrowser.DocumentComplete + = OnDocumentComplete;
}
,否则
{
webBrowser.DocumentComplete - = OnDocumentComplete;
web浏览器= NULL;
}

返回0;

}

公众诠释GetSite(REF的Guid GUID,出的IntPtr ppvSite)
{
IntPtr的朋克= Marshal.GetIUnknownForObject(网页浏览器);
INT HR = Marshal.QueryInterface(朋克,楼盘GUID,出ppvSite);
Marshal.Release(朋克);

返回小时;
}
}



IObjectWithSite.cs

 使用系统;使用System.Runtime.InteropServices 
;

命名空间IEExtensionTest
{
[标记有ComVisible特性(真)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
[的Guid(FC4801A3-2BA9-11CF -A229-00AA003D7352)]
公共接口的IObjectWithSite
{
[PreserveSig]
INT SetSite([的MarshalAs(UnmanagedType.IUnknown)对象的网站);

[PreserveSig]
INT GetSite(REF的Guid GUID,出的IntPtr ppvSite);
}
}



IExtension.cs

 使用系统;使用System.Runtime.InteropServices 
;

命名空间IEExtensionTest
{
[标记有ComVisible特性(真)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
[的Guid(FC4801A3-2BA9-11CF -A229-00AA003D7352)]
公共接口的IObjectWithSite
{
[PreserveSig]
INT SetSite([的MarshalAs(UnmanagedType.IUnknown)对象的网站);

[PreserveSig]
INT GetSite(REF的Guid GUID,出的IntPtr ppvSite);
}
}



后生成步骤如下配置(和正常运行):

 C:\Program文件(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/注销$(TARGETDIR)$(TargetFileName)
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe$(TARGETDIR )$(TargetFileName)


解决方案

我有一个hack- ý溶液于此。它现在是为我工作,所以我在这里张贴。如果我遇到任何问题,有了它,我会更新这个帖子。



@Eli Gassert正确识别的问题。在 SetSite 函数中,我们添加了一个处理程序的DocumentComplete 事件。所以,当我们在 $它不会执行。就绪()



所以,我所做的是添加处理程序BeforeScriptExecute事件。这是我BHO.cs的相关部分。



 公众诠释SetSite(对象的网站)
{
this.site =网站;
如果(网站!= NULL)
{
= web浏览器(IWebBrowser2的)站点;
((DWebBrowserEvents2_Event)浏览器上).BeforeScriptExecute + = S2_BeforeScriptExecute;
//((DWebBrowserEvents2_Event)webBrowser).DocumentComplete + = S2_DocumentComplete;
}
,否则
{
((DWebBrowserEvents2_Event)浏览器上).BeforeScriptExecute - = S2_BeforeScriptExecute;
//((DWebBrowserEvents2_Event)webBrowser).DocumentComplete - = S2_DocumentComplete;
web浏览器= NULL;
}
返回0;
}

有关处理程序的签名是不同的,这里是处理程序的代码。这仍然是BHO.cs

 私人无效S2_BeforeScriptExecute(对象pDispWindow)
{
//如果(!pDisp = this.site){返回; }

动态窗口= webBrowser.Document.parentWindow;
IExpando windowEx =(IExpando)窗口;
windowEx.AddProperty(myprop);
window.myprop =这一点;
}



我刚才粘贴从代码的的DocumentComplete 方法和注释掉顶部的条件。



这样一来,我能看到 myprop 在jQuery的 $。就绪()。这解决了我的眼前问题,我与我的代码向前迈进。



不用说,我的插件只提供了从JavaScript调用,不需要方法做文档内容什么。



我还不知道什么是 pDispWindow 键,有什么用不检查它是否为空,等的影响。


I followed this answer exactly and read and reread all google findings. Unfortunately mostly all of them simply the copy and pastes of the referenced answer (including the 'Stop banging your head against the wall and go celebrate!') sentence and it does not work for me... So after a half day working I am really about to start banging my head...

My simple error: The javascript windows.myExtension object is 'undefined' so calling Foo on it throws error. See the full source below. It seems the property set is not viewable in javascript side.

Some more information:

  • I use the Debugger.Launch() statement for convenient way to debug my extension, and the breakpoint is hit, and all BHO extension functions are properly called and run.
  • The commented alternative (with property.SetProperty) also does not work, with the same error:

    console.log(window.myExtension); // writes 'undefined', why?

  • Using VS 2010, Windows 7 x64, IE 9

Please let me help running this... Thx in advance

The simple test page:

<!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);
}
}

IExtension.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);
}
}

Post build step is configured as follows (and runs properly):

"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)"

解决方案

I have a hack-y solution to this. It is working for me right now so I am posting it here. If I encounter any issue with it, I will update this post.

@Eli Gassert identifies the problem correctly. In the SetSite function we are adding a handler to DocumentComplete event. So it would not have executed when we are in $.ready().

So what I have done is to add handler to BeforeScriptExecute event. This is the relevant part of my 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;
    }

The signature for the handler is different, and here is the code for the handler. This is still in 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;
    }

I just pasted the code from the DocumentComplete method and commented out the condition at the top.

As a result, I am able to see myprop in the jquery $.ready(). This has solved my immediate problem and I am moving ahead with my code.

Needless to say, my addon is only providing methods that will be called from javascript and does not need to do anything with document contents.

I don't yet know what is the use for pDispWindow and what is the impact of not checking if it is null, etc.

这篇关于从Javascript调用C#BHO的方法(仍然没有工作)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆