【问题标题】:ie bho IDispatchEx::Invoke failure即 bho IDispatchEx::Invoke 失败
【发布时间】:2015-02-12 21:07:29
【问题描述】:

您好,我对 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
                                    }
                                }

调用 if(FAILED( dispxWnd-&gt;Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &amp;params, NULL, NULL, NULL ))) 时失败,但仅适用于某些网站,例如 tee-links.com。 local_data.tabs[(ptr_type)browser].bho 存储指向具有已实现接口的类实例的指针。正如第一条评论所建议的那样,添加了一些代码来检索一些关于错误、快速和肮脏的信息

HRESULT hr = dispxWnd->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &params, NULL, NULL, NULL );
                                                if(FAILED(hr))
                                                {
                                                    _com_error err(hr);
                                                    LPCTSTR msg = err.ErrorMessage();
                                                    char errnum[32];
                                                    _snprintf(errnum, 31, "%x", hr);
                                                    MessageBox(NULL, msg, to_utf16(errnum).c_str(), MB_OK);

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

【问题讨论】:

  • 这是“它不起作用”的错误报告。您需要对其进行改进,以便知道它失败的原因。 HRESULT hr = dispxWnd->Invoke(..);如果(失败(小时)){...}
  • 我安装了俄罗斯操作系统,消息感类似于“未找到组成员”,十六进制错误代码 80020003
  • 您是否为您的模块创建了类型库? Here is a blog post 我很久以前写的,解释了如何走另一条路,你可能会觉得它有帮助。
  • 我认为如果没有类型库,它根本无法工作,在我的情况下,它不仅仅适用于少数几个站点,90% 的情况下它可以按预期工作。谢谢你的帖子,我没有反对 atl,而且它看起来有点难以实现,所以如果不能解决我当前 bho qrchitecture 的问题,我会保留它以供以后使用。
  • 错误码是0x80020003 DISP_E_MEMBERNOTFOUND "Member not found" 表示被调用者没有putref_这个DISPID的方法(那里没有putref_cbx)。跨度>

标签: c++ internet-explorer com atl bho


【解决方案1】:

您将获得一个带有 IDispatchEx::GetDispID 的动态 DISPID,它应该与 IDispatchEx::InvokeEx 一起使用,但随后您将它提供给 IDispatch::Invoke,它应该与 IDIspatch::GetIDsOfNames 返回的静态 DISPID 一起使用.


PS:我还觉得下面这行很有趣:

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

这些真的都是IDispatch 指针吗?或者他们是IUnknown 指针?如果是后者,那么你必须QueryInterface。

【讨论】:

  • 感谢您的回复,我会检查它,是的,所有的.bho成员都是一样的,并且已经实现了IDispatch
  • 我可以发布我的 bho 的简化示例,并实现了这个有问题的逻辑
  • 已检查,结果相同,我已上传此 bho 的简化示例(使用 IDispatchEx::Invoke)sss.chaoslab.ru/code_.7z
  • 请注意,实现IDispatch 和指向IDispatch 是两件不同的事情。如果bho 字段没有明确指向IDispatch 或派生接口,那么您必须为它QueryInterface(假设它指向IUnknown 或派生接口)。
  • 至少,您必须static_cast&lt;IDispatch*&gt;(local_data.tabs[(ptr_type)browser].bho)(或转换为Ibho*),因为bho 字段是Cbho *,才能获得IDispatch。
猜你喜欢
  • 2016-07-15
  • 1970-01-01
  • 2014-02-24
  • 2021-07-22
  • 2020-07-11
  • 2014-04-15
  • 2021-07-29
  • 1970-01-01
  • 2016-07-28
相关资源
最近更新 更多