2013-02-25 28 views
6

Tôi đã theo dõi this trả lời chính xác và đọc và đọc lại tất cả các kết quả của google. Thật không may, hầu hết tất cả chỉ đơn giản là bản sao và bột nhão của câu trả lời được tham chiếu (bao gồm câu 'Dừng đập đầu vào tường và đi ăn mừng!') Và nó không hiệu quả với tôi ... Vì vậy, sau nửa ngày làm việc, tôi thực sự sắp bắt đầu đập đầu của tôi ...Gọi phương thức C# BHO từ Javascript (vẫn không hoạt động)

Lỗi đơn giản của tôi: Đối tượng javascript windows.myExtension là 'không xác định' để gọi Foo trên đó phát sinh lỗi. Xem toàn bộ nguồn dưới đây. Có vẻ như tập hợp thuộc tính không thể xem được ở phía javascript.

Một số biết thêm thông tin:

  • tôi sử dụng câu lệnh Debugger.Launch() cho cách thuận tiện để gỡ lỗi phần mở rộng của tôi, và các breakpoint là hit, và tất cả các chức năng mở rộng BHO được gọi và chạy đúng cách.
  • Cách khác nhận xét (với property.SetProperty) cũng không hoạt động, với các lỗi tương tự:

    console.log (window.myExtension); // viết 'không xác định', tại sao?

  • Sử dụng VS 2010, Windows 7 x64, IE 9

Xin vui lòng cho tôi giúp chạy này ... Thx trước

Trang thử nghiệm đơn giản:

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

bài build bước được cấu hình như sau (và chạy đúng):

"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

Chỉ cần tham gia một đâm lúc này, nhưng có vẻ như nó chỉ thêm 'myExtension 'trên tài liệu hoàn thành. Hãy thử kiểm tra hack này: 'setTimeout (function() {console.log (window.myExtension);}, 1000);' sau 1 giây, nó sẽ xuất ra thứ gì đó trên bàn điều khiển. Tại thời điểm đó, tài liệu sẽ được tải và bạn sẽ có câu trả lời của mình. Vui lòng báo cáo lại sau bài kiểm tra này. –

+0

Thx cho ý tưởng của bạn. Tôi đã thử nó và bây giờ một lần nữa. Nó không phải là một vấn đề thời gian. window.myExtension vẫn chưa được xác định trong cuộc gọi bị trì hoãn :-( –

+0

@Dalorzo Vui lòng dừng lại với các chỉnh sửa tầm thường như thêm các thẻ mà không cần. Tôi đã liếc qua lịch sử của bạn và hầu hết các chỉnh sửa được đề xuất gần đây của bạn sẽ bị từ chối. 're unnarilyarily bumping câu hỏi cũ để trang trước bằng cách làm như vậy tầm thường (và thường sai và/hoặc không đầy đủ) chỉnh sửa –

Trả lời

0

Hãy thử với cửa sổ. bên ngoài .myExtension(); Bên ngoài là như xa như tôi nhớ đối tượng giữ hình thức của bạn. Ngoài ra nếu điều này không làm việc - hãy chắc chắn để thử những điều đơn giản đầu tiên và làm việc thay vì ngược lại.

Dưới đây là một hình thức đơn giản mà nên làm việc cho bạn:

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

Sau đó, trong trang:

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

tôi có một giải pháp hack-y này. Nó đang làm việc cho tôi ngay bây giờ vì vậy tôi đăng nó ở đây. Nếu tôi gặp bất kỳ vấn đề nào với nó, tôi sẽ cập nhật bài đăng này.

@Eli Gassert xác định vấn đề chính xác. Trong hàm SetSite, chúng tôi đang thêm một trình xử lý cho sự kiện DocumentComplete. Vì vậy, nó sẽ không thực hiện khi chúng tôi đang ở trong $.ready().

Vì vậy, những gì tôi đã làm là thêm trình xử lý vào sự kiện BeforeScriptExecute. Đây là phần liên quan của 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; 
    } 

Chữ ký cho trình xử lý khác và đây là mã cho trình xử lý. Điều này vẫn còn trong 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; 
    } 

Tôi vừa dán mã từ phương thức DocumentComplete và nhận xét điều kiện ở trên cùng.

Kết quả là tôi có thể xem myprop trong jquery $.ready(). Điều này đã giải quyết được vấn đề trước mắt của tôi và tôi đang tiến lên phía trước với mã của tôi.

Không cần phải nói, tiện ích của tôi chỉ cung cấp các phương thức sẽ được gọi từ javascript và không cần phải làm bất kỳ điều gì với nội dung tài liệu.

tôi vẫn chưa biết việc sử dụng cho pDispWindow là gì và ảnh hưởng của không kiểm tra nếu nó là null là gì vv

Các vấn đề liên quan