Вызов метода BHO из Javascript?

Я пытаюсь вызвать свой метод BHO из javascript. Проблема такая же, как указано в следующих сообщениях:

  1. Вызов BHO из функции Javascript
  2. http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/91d4076e-4795-4d9e -9b07-5b9c9eca62fb /
  3. Вызов функции C ++ из сценария JavaScript, запущенного в элементе управления веб-браузера

Третья ссылка - это еще одно сообщение SO, в котором говорится об этом, но я не понимал необходимости и кода. Также общий рабочий образец продолжает давать сбой в Windows 7 с IE 8 и Windows Vista с IE 7.

Если это помогает, мой BHO написан на C ++ с использованием ATL.

Что я пробовал:

Я написал очень простой BHO и попробовал подход, упомянутый здесь Игорем Тандетником . Никакого исключения не создается, но когда я открываю следующий html-файл в IE, он говорит object undefined .


    
        
    
    
        
Hello jQuery!!

Вопрос:

  1. Пожалуйста, поясните, возможно ли раскрыть и вызвать метод BHO из javascript или мне нужно раскрывать его с помощью activex (как ответил jeffdav в [2] )? Если да, то как это сделать.
  2. В основном я хочу расширить window.external , но способ, показанный в приведенной выше ссылке [2] , использует var x = new ActiveXObject ("MySampleATL.MyClass "); ; Оба соглашения о вызовах одинаковы или различны?

Примечание:

  1. На SO есть связанный пост, который дает подсказку, что это возможно, вставив это [id (1 ), helpstring ("method DoSomething")] HRESULT DoSomething (); в IDL-файле BHO. Я не уверен, как это было сделано, и не смог найти какой-либо вспомогательный ресурс через Google.
  2. Я знаю о это сообщение call-into-your-bho-from-a-client-script , но не пробовал, так как он решает проблему с помощью ActiveX.
  3. Моя причина избегать ActiveX в первую очередь связана с к ограничениям безопасности.

Редактировать 1


Кажется, есть способ расширить window.external. Отметьте это . В частности, раздел под названием IDocHostUIHandler::GetExternal: Extending the DOM. Теперь предположим, что наш интерфейс IDispatch находится на тот же объект, который реализует IDocHostUIHandler. Тогда мы можем сделать что-то вроде этого:

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

Проблема этого подхода заключается в том, что он не добавляется к существующим методам Windows, а скорее заменяет их. Скажите, пожалуйста, если я ошибаюсь.

Редактировать 2


Класс BHO:
class ATL_NO_VTABLE CTestScript :
    public CComObjectRootEx,
    public CComCoClass,
    public IObjectWithSiteImpl,
    public IDispatchImpl,
    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  m_spWebBrowser;
    BOOL m_fAdvised;
};

// TestScript.cpp: Реализация 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::SetSite(pUnkSite);
}

void STDMETHODCALLTYPE CTestScript::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
        CComPtr dispDoc;
        CComPtr ifDoc;
        CComPtr ifWnd;
        CComPtr 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,
            ¶ms, NULL, NULL, NULL );

}

Javascript:


Редактировать 3


Потратив на это три дня, я думаю, что мне следует взять путь ActiveX. Написание базового ActiveX - это просто способ сделать его простым, написанным и протестированным на всех основных выпусках IE. Я оставляю этот вопрос открытым, см. Комментарии в ответе Ури (большое ему спасибо). Я испробовал большинство его предложений (кроме 4 и 5). I will also suggest you to see the MSDN IDispatcEx sample. Если вы найдете решение, напишите, если я найду решение, я обязательно обновлю его здесь.

Редактировать 4


См. Мой последний комментарий в сообщении URI. Проблема решена.

10
задан Community 23 May 2017 в 12:07
поделиться