我正在使用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
”的代码。