C++ ie bho IDispatchEx::调用失败

C++ ie bho IDispatchEx::调用失败,c++,internet-explorer,com,atl,bho,C++,Internet Explorer,Com,Atl,Bho,您好,我对internet explorer的浏览器帮助对象有问题。我需要从页面中注入的JS代码调用我的C++代码,所以我必须导出一些C++方法到JS代码。我通过IDispatchEx::Invoke找到了这个方法,但对于某些站点,这个方法经常失败 void __stdcall CEventSink::DocumentComplete(IDispatch *pObject, VARIANT *pvarUrl) { if(pObject) { IServicePro

您好,我对internet explorer的浏览器帮助对象有问题。我需要从页面中注入的JS代码调用我的C++代码,所以我必须导出一些C++方法到JS代码。我通过
IDispatchEx::Invoke
找到了这个方法,但对于某些站点,这个方法经常失败

void __stdcall CEventSink::DocumentComplete(IDispatch *pObject, VARIANT *pvarUrl)
{
    if(pObject)
    {
        IServiceProvider *pSp = NULL;
        if(SUCCEEDED(pObject->QueryInterface(IID_IServiceProvider, (void**)&pSp)))
        {
            IWebBrowser2 *browser = NULL;
            if(SUCCEEDED(pObject->QueryInterface(IID_IWebBrowser2, (void**)&browser)))
            {
            IDispatch *disp = NULL;
            if(SUCCEEDED(browser->get_Document(&disp)))
            {
                IHTMLDocument2 *doc = NULL;
                if(SUCCEEDED(disp->QueryInterface(IID_IHTMLDocument2, (void**)&doc)))
                {
                    IHTMLWindow2 *w = NULL;
                    if(SUCCEEDED(doc->get_parentWindow(&w)))
                    {
                        CComPtr<IDispatchEx> dispxWnd;
                        if(local_data.tabs[(ptr_type)browser].bho)
                        {
                            if(SUCCEEDED(w->QueryInterface( &dispxWnd )))
                            {
                                CComBSTR propName( L"cbx" );
                                DISPID dispid;
                                if(SUCCEEDED ( dispxWnd->GetDispID( propName, fdexNameEnsure, &dispid )))
                                {
                                    CComVariant varMyBho( (IDispatch*)local_data.tabs[(ptr_type)browser].bho );
                                    DISPID dummy[] = {DISPID_PROPERTYPUT};
                                    DISPPARAMS params;
                                    params.cArgs = 1;
                                    params.cNamedArgs = 0;
                                    params.rgvarg = &varMyBho;
                                    params.rgdispidNamedArgs = NULL;
                                    if(FAILED( dispxWnd->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &params, NULL, NULL, NULL )))
                                    {
                                        MessageBoxA(NULL, "failed to dispxWnd->Invoke", "", MB_OK);
                                        //TODO: handle error
                                    }
                                }

因此,我们有类似“找不到组成员”的错误消息,我安装了俄语操作系统,因此不能准确地说,错误代码80020003

您将得到一个带有
IDispatchEx::GetDispID
的动态DISPID,它应该与
IDispatchEx::InvokeEx
一起工作,但随后您将它提供给
IDispatch::Invoke
,它应该与
IDispatch::GetIDsOfNames
返回的静态dispid一起工作


附言:我也觉得下面这句话很有趣:

CComVariant varMyBho( (IDispatch*)local_data.tabs[(ptr_type)browser].bho );

这些真的都是
IDispatch
指针吗?或者它们是
IUnknown
指针?如果是后者,则必须
QueryInterface

这是“它不工作”错误报告。你需要改进它,以便知道它失败的原因。HRESULT hr=dispxWnd->Invoke(..);如果(FAILED(hr)){…}我已经安装了俄语操作系统,消息的含义类似于“找不到组成员”,十六进制错误代码80020003您是否为模块创建了类型库?我很久以前写过一篇文章,解释了如何使用其他方法,你可能会发现它很有用。我认为如果没有类型库,它根本不会工作,在我的情况下,它不会只在少数几个网站上工作,因为90%的网站都能正常工作。谢谢你的帖子,我不反对atl,它看起来对我来说有点难实现,所以如果不能解决我当前bho体系结构的问题,我会保留这个供以后使用。错误代码是
0x80020003
DISP_E_MEMBERNOTFOUND
“Member notfound”它表明被调用方没有用于此
DISPID
(没有
putref\u cbx
)的
putref\u
方法。感谢您的回复,我会检查它,是的,所有.bho成员都是相同的,并且IDispatch已实现。我可以发布我的bho的简化示例,并实现此有问题的逻辑检查,相同的结果,我上传了这个bho的简化示例(使用IDispatchEx::Invoke),注意实现
IDispatch
和作为
IDispatch
的指针是两件不同的事情。如果
bho
字段未明确指向
IDispatch
或派生接口,则必须为其
QueryInterface
(假设它指向
IUnknown
或派生)。至少,必须
静态转换(本地数据.tabs[(ptr_类型)浏览器].bho)
(或转换到
Ibho*
),由于
bho
字段是
Cbho*
,因此要获得
IDispatch
CComVariant varMyBho( (IDispatch*)local_data.tabs[(ptr_type)browser].bho );