2013-02-25 15 views
6

Ho seguito esattamente this e ho letto e riletto tutti i risultati di Google. Sfortunatamente per la maggior parte tutte semplicemente la copia e le paste della risposta di riferimento (compresa la frase "Smettila di sbattere la testa contro il muro e vai a festeggiare!") E non funziona per me ... Quindi dopo mezza giornata di lavoro sono sto per iniziare a picchiarmi la testa ...Chiamare i metodi C# BHO da Javascript (ancora non funzionante)

Il mio semplice errore: L'oggetto javascript windows.myExtension è 'indefinito' quindi chiamare Foo su di esso genera un errore. Vedi l'intera fonte qui sotto. Sembra che il set di proprietà non sia visibile in javascript.

Qualche informazione in più:

  • Io uso la dichiarazione Debugger.Launch() per modo conveniente per eseguire il debug mia estensione, e il punto di interruzione viene colpito, e tutte le funzioni di estensione BHO verranno giustamente chiamati ed eseguire.
  • L'alternativa commentato (con property.SetProperty) non funziona inoltre, con lo stesso errore:

    console.log (window.myExtension); // scrive 'indefinito', perché?

  • Utilizzando VS 2010, Windows 7 x64, IE 9

prega lascia che ti aiuti al funzionamento di questo ... Thx in anticipo

La semplice pagina di prova:

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

fase di post build è configurato come segue (e gira correttamente):

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

Basta prendere una pugnalata a questo, ma sembra che solo aggiunge 'myextension 'sul documento completo. Prova questo hack test: 'setTimeout (function() {console.log (window.myExtension);}, 1000);' dopo 1 secondo dovrebbe produrre qualcosa sulla console. A quel punto, il documento dovrebbe essere caricato e dovresti avere la tua risposta. Si prega di segnalare dopo questo test. –

+0

Thx per la tua idea. L'ho già provato e ora di nuovo. Non è un problema di temporizzazione. window.myExtension è ancora indefinito nella chiamata ritardata :-( –

+0

@Dalorzo Si prega di interrompere con modifiche banali come l'aggiunta di tag dove non è necessario. Ho dato un'occhiata alla cronologia e la maggior parte delle tue modifiche suggerite recenti avrebbe dovuto essere respinta. 'inutilmente bump vecchie domande alla prima pagina facendo tali modifiche banali (e spesso errate e/o incomplete.) –

risposta

0

provare con finestra. esterno .myExtension(); Esterno è per quanto mi ricordo dell'oggetto che contiene il tuo modulo. Anche se questo non funziona, assicurati di provare prima le cose semplici e lavorare invece il contrario.

Ecco un semplice modulo che dovrebbe funzionare per voi:

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

Poi nella pagina:

$(document).ready(function() { 
    alert(window.external.TestMethod("It will hopefully work.")); 
} 
0

ho una soluzione hack-y a questo. Funziona per me adesso, quindi lo sto postando qui. Se dovessi riscontrare un problema con esso, aggiornerò questo post.

@Eli Gassert identifica correttamente il problema. Nella funzione SetSite stiamo aggiungendo un gestore all'evento DocumentComplete. Quindi non avrebbe eseguito quando siamo in $.ready().

Quindi, ciò che ho fatto è aggiungere il gestore all'evento BeforeScriptExecute. Questa è la parte rilevante delle mie 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; 
    } 

La firma per il gestore è diverso, ed ecco il codice per il gestore. Questo è ancora 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; 
    } 

ho appena incollato il codice dal metodo DocumentComplete e commentato la condizione in alto.

Come risultato, sono in grado di vedere myprop nella jquery $.ready(). Questo ha risolto il mio problema immediato e sto andando avanti con il mio codice.

Inutile dire che il mio addon fornisce solo metodi che verranno chiamati da javascript e non ha bisogno di fare nulla con il contenuto del documento.

io non so ancora che cosa è l'uso per pDispWindow e qual è l'impatto di non controllare se è nullo, ecc

Problemi correlati