2012-01-11 24 views
10

BHO yöntemimi javascript'ten aramaya çalışıyorum. şu yayınlarda belirtildiği gibi sorun aynıdır:Javascript'ten BHO yöntemini mi arıyorsunuz?

  1. Call BHO from Javascript function
  2. http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/91d4076e-4795-4d9e-9b07-5b9c9eca62fb/
  3. Calling C++ function from JavaScript script running in a web browser control

Üçüncü bağlantı başka SO bu konuda konuşmak sonrası ama anlamadı ihtiyaç ve kod. Ayrıca, paylaşılan çalışma örneği, Windows 7'de 8 ve Windows 7'de Windows 7'de kilitlenme yapmaya devam eder. Örneğin,

Eğer BHO'um AT + kullanarak C++ dilinde yazılırsa. Ben denedim ne

: Ben çok temel bir BHO'yu yazılı ve İgor Tandetnik tarafından bahsedilen here olarak yaklaşımını denedi

. Hiçbir özel durum oluşturulur, ancak IE'de aşağıdaki html dosyasını açtığımda nesnesi tanımlanmamış diyor.

<html> 
    <head> 
     <script language='javascript'> 
      function call_external(){ 
       try{ 
       alert(window.external.TestScript); 
       //JQueryTest.HelloJquery('a'); 
       }catch(err){ 
        alert(err.description); 
       } 
      } 
     </script> 
    </head> 
    <body id='bodyid' onload="call_external();"> 
     <center><div><span>Hello jQuery!!</span></div></center> 
    </boay> 
</html> 

Soru:

  1. teşhir ve javascript dan BHO yöntemini çağırın veya [2] yılında jeffdav tarafından yanıtlandı olarak ben bir activex (kullanarak maruz zorunda yapmak mümkün olup olmadığını açıklığa kavuşturmak Lütfen)? Eğer evetse o zaman nasıl yapılır.
  2. Temel olarak window.external'u genişletmek istiyorum ancak yukarıdaki bağlantıda gösterilen yol [2]var x = new ActiveXObject("MySampleATL.MyClass");; Hem çağrı kuralları hem de aynı mıdır?

Not:

  1. o BHO IDL dosyasında bu [id(1), helpstring("method DoSomething")] HRESULT DoSomething(); ekleme yoluyla mümkün olduğunu ima verir SO üzerinde ilgili yayın yoktur. Google’dan nasıl yapıldığını ve destekleyici bir kaynak bulamadığından emin değilim.
  2. Bu iletinin farkındayım calling-into-your-bho-from-a-client-script, ancak ActiveX kullanarak sorunu çözdüğü için denemedim.
  3. ActiveX'ten sakınma nedenim temel olarak güvenlik kısıtlamalarından kaynaklanmaktadır.

düzenleme 1


O window.external uzatmak için bir yol var gibi görünüyor. this’u kontrol edin. Özel olarak IDocHostUIHandler::GetExternal: Extending the DOM. başlıklı bölüm Artık IDispatch arayüzümüzü kabul etmek IDocHostUIHandler'ı uygulayan aynı nesnede.Sonra böyle bir şey yapabilirsiniz: Bu yaklaşım ile mevcut pencereleri yöntemlere eklenecek alışkanlık olduğunu

HRESULT CBrowserHost::GetExternal(IDispatch **ppDispatch) 
{ 
    *ppDispatch = this; 
    return S_OK; 
} 

sorunu değil, bunların yerine. Lütfen yanlış olup olmadığımı söyle.

Düzenleme 2


The BHO Class:

class ATL_NO_VTABLE CTestScript : 
    public CComObjectRootEx<CComSingleThreadModel>, 
    public CComCoClass<CTestScript, &CLSID_TestScript>, 
    public IObjectWithSiteImpl<CTestScript>, 
    public IDispatchImpl<ITestScript, &IID_ITestScript, &LIBID_TestBHOLib, /*wMajor =*/ 1, /*wMinor =*/ 0>, 
    public IDispEventImpl<1, CTestScript, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1> 
{ 
public: 
    CTestScript() 
    { 
    } 

DECLARE_REGISTRY_RESOURCEID(IDR_TESTSCRIPT) 

DECLARE_NOT_AGGREGATABLE(CTestScript) 

BEGIN_COM_MAP(CTestScript) 
    COM_INTERFACE_ENTRY(ITestScript) 
    COM_INTERFACE_ENTRY(IDispatch) 
    COM_INTERFACE_ENTRY(IObjectWithSite) 
END_COM_MAP() 



    DECLARE_PROTECT_FINAL_CONSTRUCT() 

    HRESULT FinalConstruct() 
    { 
     return S_OK; 
    } 

    void FinalRelease() 
    { 
    } 

public: 
    BEGIN_SINK_MAP(CTestScript) 
     SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) 
     //SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, OnNavigationComplete) 
    END_SINK_MAP() 

    void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL); 
    //void STDMETHODCALLTYPE OnNavigationComplete(IDispatch *pDisp, VARIANT *pvarURL); 

    STDMETHOD(SetSite)(IUnknown *pUnkSite); 

    HRESULT STDMETHODCALLTYPE DoSomething(){ 
     ::MessageBox(NULL, L"Hello", L"World", MB_OK); 
     return S_OK; 
    } 
public: 

//private: 
    // InstallBHOMethod(); 

private: 
    CComPtr<IWebBrowser2> m_spWebBrowser; 
    BOOL m_fAdvised; 
}; 

// TestScript.cpp : Implementation of CTestScript

#include "stdafx.h" 
#include "TestScript.h" 


// CTestScript 

STDMETHODIMP CTestScript::SetSite(IUnknown* pUnkSite) 
{ 
    if (pUnkSite != NULL) 
    { 
     HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser); 
     if (SUCCEEDED(hr)) 
     { 
      hr = DispEventAdvise(m_spWebBrowser); 
      if (SUCCEEDED(hr)) 
      { 
       m_fAdvised = TRUE;    
      } 
     } 
    }else 
    { 
     if (m_fAdvised) 
     { 
      DispEventUnadvise(m_spWebBrowser); 
      m_fAdvised = FALSE; 
     } 
     m_spWebBrowser.Release(); 
    } 
    return IObjectWithSiteImpl<CTestScript>::SetSite(pUnkSite); 
} 

void STDMETHODCALLTYPE CTestScript::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) 
{ 
     CComPtr<IDispatch> dispDoc; 
     CComPtr<IHTMLDocument2> ifDoc; 
     CComPtr<IHTMLWindow2> ifWnd; 
     CComPtr<IDispatchEx> dispxWnd; 

     HRESULT hr = m_spWebBrowser->get_Document(&dispDoc); 
     hr = dispDoc.QueryInterface(&ifDoc);  
     hr = ifDoc->get_parentWindow(&ifWnd); 
     hr = ifWnd.QueryInterface(&dispxWnd); 

     // now ... be careful. Do exactly as described here. Very easy to make mistakes 
     CComBSTR propName(L"myBho"); 
     DISPID dispid; 
     hr = dispxWnd->GetDispID(propName, fdexNameEnsure, &dispid); 

     CComVariant varMyBho((IDispatch*)this); 
     DISPPARAMS params; 
     params.cArgs = 1; 
     params.cNamedArgs = 0; 
     params.rgvarg = &varMyBho;    
     params.rgdispidNamedArgs = NULL; 
     hr = dispxWnd->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, 
      &params, NULL, NULL, NULL); 

} 

The Javascript:

<script language='javascript'> 
      function call_external(){ 
       try{ 
       alert(window.ITestScript); 
       }catch(err){ 
        alert(err.description); 
       } 
      } 
     </script> 

bu üç gün geçirdikten sonra Düzen 3


, ben ActiveX yolu almak gerektiğini düşünüyorum. Temel bir activex yazmanın yolu, basit, yazılı bir yoldur ve tüm önemli IE sürümlerinde test edilir. Bu soruyu açık olarak bırakıyorum, lütfen Uri'nin cevabındaki yorumları görün (ona çok teşekkürler). Onun önerilerinin çoğunu denedim (4 ve 5 hariç). I will also suggest you to see the MSDN IDispatcEx sample. Eğer bir çözüm bulursanız lütfen gönderin, eğer bir çözüm bulursam kesinlikle buradan güncelleme yapacağım.

Düzenleme 4


See my last comment in URI's post. Issue Resolved.

cevap

7

İgor Tandetnik yöntemi doğru bir yaklaşımdır. Gönderi ile ilgili sorun, örnek kodun (en azından onu gördüğüm birkaç sayfada) tamamlanmamış olmasıdır. Çalışana kadar birçok deneme ve hata yaptım. İşte hile yok benim kod iyi yığınıdır:

Bir sınıfı CMyBho var ki, ve Java komut dosyaları için IMyBho otomasyon nesne sergilemek istediğiniz

Sınıf tanımı: Standart CComObjectRootEx kaynaklanıyor
ve CComCoClass bunu 'birlikte yaratılabilir' yapmak. IObjectWithSiteImpl (bu temel sınıf tarafından uygulanan m_spUnkSite'yi yeniden kullanacaksınız) var. IDispatchImpl otomasyon nesnesi uygular ve IDispatchEventImpl tarayıcıdan bildirim almak için lavabo geçerli:

class ATL_NO_VTABLE CMyBho 
    : public CComObjectRootEx<CComSingleThreadModel> 
    , public CComCoClass<CMyBho, &CLSID_MyBho> 
    , public IObjectWithSiteImpl<CMyBho> 
    , public IDispatchImpl<IMyBho, &IID_IMyBho, &LIBID_MyBhoLib, 1, 0> 
    , IDispatchEventImpl<1, CMyBho, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1> 
{ 
    ... 

public: 
    BEGIN_COM_MAP(CMyBho) 
     COM_INTERFACE_ENTRY(IMyBho) 
     COM_INTERFACE_ENTRY(IDispatch) 
     COM_INTERFACE_ENTRY(IObjectWithSite) 
    END_COM_MAP() 

    ... 

    BEGIN_SINK_MAP(CMyBho) 
     SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocComplete) 
    END_SINK_MAP() 

    ... 

private: 
    CComPtr<IWebBrowser2> m_ifbrz;   // pointer to the hosting browser 

} 

Sonraki, SetSite yöntemi, bildirime olmak için kaydolun. Temel sınıfı çağırmayı unutma. Belge yük tamamlandığında

STDMETHODIMP CMyBho::SetSite(IUnknown* unkSite) 
{ 
    ... 
    hr = IObjectWithSiteImpl::SetSite(unkSite); 
    if(unkSite) { 
     ... 
     // advise to browser event. 
     CComPtr<IServiceProvider> ifsp; 
     hr = m_spUnkSite.QueryInterface(&ifsp); 
     hr = ifsp->QueryService(SID_SwebBrowserApp, IID_IWebBrowser2, &m_ifbrz); 
     hr = DispEventAdvise(m_ifbrz); 
    } 
    else { 
     // release various resources (m_ifbrz will be released automatically by its dtor) 
     ... 
    } 
... 
} 

bu işlev çağrılır:

sizin diğer sorular gelince
void STDMETHODCALLTYPE CMyBho::onDocComplete(IDispatch* dispBrz, VARIANT* pvarUrl) 
{ 
    CComPtr<IDispatch> dispDoc; 
    CComPtr<IHTMLDocument2> ifDoc; 
    CComPtr<IHTMLWindow2> ifWnd; 
    CComPtr<IDispatchEx> dispxWnd; 

    hr = m_ifbrz->get_Document(&dispDoc); 
    hr = dispDoc.QueryInterface(&ifDoc);  
    hr = ifDoc->get_parentWindow(&ifWnd); 
    hr = ifWnd.QueryInterface(&dispxWnd); 

    // now ... be careful. Do exactly as described here. Very easy to make mistakes 
    CComBSTR propName(L"myBho"); 
    DISPID dispid; 
    hr = dispxWnd->GetDispID(propName, fdexNameEnsure, &dispid); 

    CComVariant varMyBho((IDispatch*)this); 
    DISPPARAMS params; 
    params.cArgs = 1; 
    params.cNamedArgs = 0; 
    params.rgvarg = &varMyBho;    
    params.rgdispidNamedArgs = NULL; 
    hr = dispxWnd->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, 
          &params, NULL, NULL, NULL); 
} 

:

Anlaşılan
  • , cevabım yapabilirsiniz bir otomasyon yapar ima BHO'nuzdan komut dosyası için kullanılabilir nesne. Nesnenin yeni ActiveXObject ile başlatılması da mümkündür.Bu durumda, IE'ye nesnenizin komut dosyası için güvenli olduğunu söylemeyi unutmayın (yan not: BHO'nuzu komut dosyası için güvenli hale getirin. Kötü amaçlı web sitesinin BHO'nuzu kullanamayacağından emin olun).

  • Bu window.myBho, window.external.myBho'dan daha iyi bir yer olduğunu düşünüyorum. Semantik olarak, 'external', mshtml tarayıcı denetiminin başka bir uygulamada barındırıldığı zamandır.

Bu yardımcı oldu umarım.

+0

Cevabınız için teşekkür ederiz. Önerinizi denedim ama javascriptimde bho nesnesine eriştiğimde bana 'object undefined' veriyor. Lütfen güncellenmiş cevabımı görün, BHO kodunu ve ilgili javascript'i ekledim. – Favonius

+0

Bu iki ifadeyi değiştirdim params.rgvarg = & varTanduBar; params.rgdispidNamedArgs = null; 'buna' params.rgvarg = & varMyBho; params.rgdispidNamedArgs = NULL; '. Aksi takdirde aynı kodu kullandım. – Favonius

+0

Ayrıca, DISPATCH_PROPERTYPUTREF ve DISPATCH_PROPERTYPUT işlevlerini denedim. Ama bu durumda her ikisi de çalışmıyor. – Favonius

İlgili konular