我正在使用ATL编写BHO,并且正在使用DispEventUnadvise作为SetSite函数的一部分来与Internet Explorer断开连接。

这是我的代码:

STDMETHODIMP FooBho::SetSite(IUnknown* site)
{
    if (site != nullptr)
    {
        if( this->webBrowser != nullptr )
        {
            this->webBrowser.Release();
        }
        // Cache the pointer to IWebBrowser2.
        HRESULT hr = site->QueryInterface(IID_IWebBrowser2, (void**) &this->webBrowser);
        ATLENSURE_SUCCEEDED(hr);

        // Register event-handler.
        hr = DispEventAdvise(this->webBrowser);
        ATLENSURE_SUCCEEDED(hr);

        this->isAdvised = true;
    }
    else
    {
        // Release cached pointers and other resources here.
        if( this->isAdvised )
        {
            HRESULT hr = DispEventUnadvise( this->webBrowser );
            ATLENSURE_SUCCEEDED(hr); // This assertion often fails when hr == 0x80040200
            this->isAdvised = false;
        }

        this->webBrowser.Release();
    }

    // Return the base class implementation
    return IObjectWithSiteImpl<FooBho>::SetSite(site);
}


DispEventUnadvise很多时候会返回0x80040200,它对应于许多不同的HRESULT,但是我认为它对应于EVENT_E_FIRST,但是我不确定,DispEventUnadvise的文档没有记录其错误代码。

ATLENSURE_SUCCEEDED中断言失败会导致BHO崩溃,因此我需要将其删除,但是完全忽略DispEventUnadvise的返回值是否安全还是应该检查0x80040200还是仍然调用ATLENSURE_SUCCEEDED

更新资料

这是我班的标头,其中包括水槽图:

// FooBho.h : Declaration of the CFooBho

#pragma once
#include "resource.h"       // main symbols

#include <ShlGuid.h> // IID_IWebBrowser2, DIID_DWebBrowserEvents2, etc.
#include <exdispid.h> // DISPID_DOCUMENTCOMPLETE, etc.
#include <MsHTML.h>

#include "Bho_i.h"

using namespace ATL;

const int DispatchInterface1 = 1;

class ATL_NO_VTABLE FooBho :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<FooBho, &CLSID_FooBho>,
    public IObjectWithSiteImpl<FooBho>,
    public IDispatchImpl<IFooBho, &IID_IFooBho, &LIBID_BhoLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
    public IDispEventImpl<DispatchInterface1, FooBho, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
{
private:

    CComPtr<IWebBrowser2> webBrowser;
    bool                  isAdvised;

public:
    FooBho()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_FOOBHO)

DECLARE_NOT_AGGREGATABLE(FooBho)

BEGIN_COM_MAP(FooBho)
    COM_INTERFACE_ENTRY(IFooBho)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()

    STDMETHOD(SetSite)(IUnknown *site) override;

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }

#pragma region DIID_DWebBrowserEvents2

    BEGIN_SINK_MAP(FooBho)
        SINK_ENTRY_EX(DispatchInterface1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
    END_SINK_MAP()

    void STDMETHODCALLTYPE OnDocumentComplete(IDispatch* dispatch, VARIANT* uri);

#pragma endregion

private:

    long RemoveImages(IHTMLDocument2* document);

};

OBJECT_ENTRY_AUTO(__uuidof(FooBho), FooBho)

最佳答案

错误代码代表CONNECT_E_NOCONNECTION,大概是内部IConnectionPointContainer::FindConnectionPoint调用返回的。也就是说,没有连接点,接收器映射出了点问题,您没有包括在内。

您的代码段中还有其他错误。 ATLENSURE_SUCCEEDED的使用不正确。从COM方法返回之前,它将引发您应该捕获的异常。

STDMETHODIMP FooBho::SetSite(IUnknown* site)
{
  _ATLTRY
  {
    // ...
    ATLENSURE_SUCCEEDED(...);
    // ...
  }
  _ATLCATCH(Exception)
  {
    return Exception;
  }
  return S_OK;
}


安全忽略的错误代码将是告诉“不建议您使用Unadvise”的代码。

10-08 11:12