2013-02-25 20 views
6

Śledziłem this odpowiedź dokładnie i czytać i ponownie przeczytać wszystkie google ustaleń. Niestety w większości wszystkie z nich po prostu kopia i pasty do którego odnosi się odpowiedź (w tym "Przestań walić głową o ścianę i iść świętować!) Zdanie i to nie działa dla mnie ... Więc po pół dnia pracy jestem naprawdę zacznie się walić w głowę ...Wywoływanie C# BHO metody z JavaScript (jeszcze nie działa)

Mój prosty błąd: Obiekt javascript windows.myExtension jest "niezdefiniowany", więc wywołanie Foo na nim powoduje błąd. Zobacz pełne źródło poniżej. Wygląda na to, że zestaw właściwości nie jest widoczny po stronie javascript.

Niektórzy więcej informacji:

  • używam Debugger.Launch() oświadczenie o wygodny sposób debugowania mojego rozszerzenie, a punkt przerwania jest trafiony, a wszystkie funkcje rozszerzające BHO są właściwie nazywa i run.
  • komentowanym alternatywa (z property.SetProperty) również nie działa, z tym samym błędem:

    console.log (window.myExtension); // pisze "niezdefiniowany", dlaczego?

  • Korzystanie VS 2010, Windows 7 x64, IE 9

Proszę, pozwól mi pomóc to działa ... Thx z góry

Prosta strona testowa:

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

build post krokiem jest skonfigurowany w następujący sposób (i działa poprawnie):

"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

Tylko biorąc ukłucie na to, ale wygląda na to, że tylko dodaje 'myExtension 'na kompletnym dokumencie. Spróbuj tego testu hack: 'setTimeout (function() {console.log (window.myExtension);}, 1000);' po 1 sekundzie powinien wypisać coś na konsolę. W tym momencie dokument powinien zostać załadowany i powinieneś mieć swoją odpowiedź. Po tym teście zgłoś się ponownie. –

+0

Thx za twój pomysł. Już wypróbowałem to i teraz znowu. To nie jest problem z timingiem. window.myExtension jest wciąż niezdefiniowany w opóźnionym wywołaniu :-( –

+0

@Dalorzo Proszę zatrzymać się z drobnymi zmianami, takimi jak dodawanie tagów tam, gdzie nie są potrzebne. Przejrzałem historię, a większość ostatnio sugerowanych zmian powinna zostać odrzucona. "niepotrzebnie przerzucam stare pytania na pierwszą stronę, robiąc takie banalne (i często błędne i/lub niepełne) edycje." –

Odpowiedz

0

spróbować z okna. zewnętrzny .myExtension(); zewnętrzna jest o ile pamiętam obiekt, który posiada swoją formę. jeśli to nie zadziała także - należy spróbować prostych rzeczy pierwszy i pracować, a nie odwrotnie.

Oto prosty formularz, który powinien pracować dla Ciebie:

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

Następnie na stronie:

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

Mam hack-y rozwiązanie tego. W tej chwili działa dla mnie, więc zamieszczam go tutaj. Jeśli napotkam jakiś problem, zaktualizuję ten wpis.

@ ALli Gassert identyfikuje problem poprawnie. W funkcji SetSite dodajemy obsługę do zdarzenia DocumentComplete. Więc nie zostałoby wykonane, gdy jesteśmy w $.ready().

Więc to, co zrobiłem, to dodanie programu obsługi do zdarzenia BeforeScriptExecute. Jest to odpowiednia część moich 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; 
    } 

Podpis dla obsługi jest inny, a tutaj jest kod dla obsługi. To jest nadal w 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; 
    } 

właśnie wklejony kod z metody DocumentComplete i wykomentowane stan na szczycie.

W rezultacie mogę zobaczyć myprop w jquery $.ready(). To rozwiązało mój natychmiastowy problem i postępuję dalej z moim kodem.

Nie muszę dodawać, że mój dodatek dostarcza tylko metody, które będą wywoływane z javascript i nie będzie musiał nic robić z zawartością dokumentu.

ja jeszcze nie wiem jaki jest pożytek dla pDispWindow i jaki jest wpływ nie sprawdzając, czy jest null, itp

Powiązane problemy