6

私はこの回答に正確に従い、すべてのGoogleの調査結果を読んで読み直しました。残念ながら、それらのほとんどすべては、参照されている回答のコピーと貼り付け(「頭を壁にぶつけるのをやめて、祝いに行きましょう!」を含む)の文であり、私にはうまくいきません...だから、半日働いた後、私は本当に頭をぶつけそうになる...

私の単純なエラー: javascript windows.myExtension オブジェクトは「未定義」であるため、Foo を呼び出すとエラーがスローされます。以下の完全なソースを参照してください。プロパティ セットが JavaScript 側で表示できないようです。

いくつかの詳細情報:

  • 拡張機能をデバッグする便利な方法として Debugger.Launch() ステートメントを使用すると、ブレークポイントがヒットし、すべての BHO 拡張機能が適切に呼び出されて実行されます。
  • コメント付きの代替 (property.SetProperty を使用) も機能せず、同じエラーが発生します。

    console.log(window.myExtension); // 'undefined' と書き込みます。なぜですか?

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

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

ビルド後のステップは次のように構成されます (適切に実行されます)。

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

2 に答える 2

1

これにはハックな解決策があります。それは今私のために働いているので、ここに投稿しています。問題が発生した場合は、この投稿を更新します。

@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上部の条件をコメントアウトしました。

その結果、mypropjquery で見ることができ$.ready()ます。これで当面の問題は解決し、コードを進めています。

言うまでもなく、私のアドオンは JavaScript から呼び出されるメソッドのみを提供しており、ドキュメントの内容に対して何もする必要はありません。

pDispWindow何に使用されるのか、null かどうかをチェックしないことの影響などはまだわかりません。

于 2016-01-27T13:10:13.790 に答える
0

ウィンドウで試してください。外部.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."));
}
于 2014-02-27T16:26:27.677 に答える