Outlook Addin: исключение DispEventAdvise - PullRequest
0 голосов
/ 14 мая 2010

Я хочу создать надстройку, которая будет захватывать при {создании, редактировании, удалении {контакт, календарь, задача, заметка}. У меня есть следующий код, чтобы сделать его короче, я удалил весь код, но связанный с контактом, так как я думаю, что все типы будут одинаковыми.

AutoSync.h

class ATL_NO_VTABLE AutoSync : 
 public wxPanel,
 public IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)>,
 public IDispEventSimpleImpl<2, AutoSync, &__uuidof(Outlook::ItemsEvents)>,
 public IDispEventSimpleImpl<3, AutoSync, &__uuidof(Outlook::ItemsEvents)>
{
public:
 AutoSync();
 ~AutoSync();

 void __stdcall OnItemAdd(IDispatch* Item); /* 0xf001 */
 void __stdcall OnItemChange(IDispatch* Item); /* 0xf002 */ 
 void __stdcall OnItemRemove(); /* 0xf003 */

 BEGIN_SINK_MAP(AutoSync)
  SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf001, OnItemAdd, &OnItemsAddInfo)
  SINK_ENTRY_INFO(2, __uuidof(Outlook::ItemsEvents), 0xf002, OnItemChange, &OnItemsChangeInfo)
  SINK_ENTRY_INFO(3, __uuidof(Outlook::ItemsEvents), 0xf003, OnItemRemove, &OnItemsRemoveInfo)
 END_SINK_MAP()

 typedef IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemAddEvents;
 typedef IDispEventSimpleImpl<2, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemChangeEvents;
 typedef IDispEventSimpleImpl<3, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemRemoveEvents;

    private:

    CComPtr<Outlook::_Items> m_contacts;

    };

AutoSync.cpp

 _NameSpacePtr pMAPI = OutlookWorker::GetInstance()->GetNameSpacePtr();


MAPIFolderPtr pContactsFolder = NULL;
 HRESULT hr = NULL;

 //get folders
 if(pMAPI != NULL) {
  pMAPI->GetDefaultFolder(olFolderContacts, &pContactsFolder);
 }

 //get items
 if(pContactsFolder != NULL) pContactsFolder->get_Items(&m_contacts);

 //dispatch events
 if(m_contacts != NULL) {
    //HERE COMES THE EXCEPTION
  hr = ItemAddEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemChangeEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemRemoveEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
 }

где-то еще определено:

extern _ATL_FUNC_INFO OnItemsAddInfo;
extern _ATL_FUNC_INFO OnItemsChangeInfo;
extern _ATL_FUNC_INFO OnItemsRemoveInfo;
_ATL_FUNC_INFO OnItemsAddInfo = {CC_STDCALL,VT_EMPTY,1,{VT_DISPATCH}};
_ATL_FUNC_INFO OnItemsChangeInfo = {CC_STDCALL,VT_EMPTY,1,{VT_DISPATCH}};
_ATL_FUNC_INFO OnItemsRemoveInfo = {CC_STDCALL,VT_EMPTY,0};

Проблема возникает в

    hr = ItemAddEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemChangeEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));
  hr = ItemRemoveEvents::DispEventAdvise((IDispatch*)m_contacts,&__uuidof(Outlook::ItemsEvents));

Выдает исключение в atlbase.inl при выполнении метода Advise:

ATLINLINE ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw)
{
 if(pUnkCP == NULL)
  return E_INVALIDARG;

 CComPtr<IConnectionPointContainer> pCPC;
 CComPtr<IConnectionPoint> pCP;
 HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
 if (SUCCEEDED(hRes))
  hRes = pCPC->FindConnectionPoint(iid, &pCP);
 if (SUCCEEDED(hRes))
    //HERE GIVES EXCEPTION
    //Unhandled exception at 0x2fe913e3 in OUTLOOK.EXE: 0xC0000005: 
    //Access violation reading location 0xcdcdcdcd.
  hRes = pCP->Advise(pUnk, pdw);
 return hRes;
}

Я не могу понять, почему. Любое предложение здесь? Все вроде бы хорошо, но явно нет. Я застрял здесь довольно долго. Нужна ваша помощь, спасибо.

Ответы [ 3 ]

0 голосов
/ 12 июня 2010

У меня была похожая проблема, причина в том, что я вызывал виртуальные методы из конструктора. Если ваш код находится в конструкторе, попробуйте переместить его в FinalConstruct ().

0 голосов
/ 26 октября 2012

Я когда-либо сталкивался с этим исключением, удаление ATL_NO_VTABLE может исправить это.

0 голосов
/ 14 мая 2010

Первый факт из краткого обзора заключается в том, что вам нужно получить только один IDispEventSimpleImpl на интерфейс - вам не нужен один для каждого метода интерфейса:

class ATL_NO_VTABLE AutoSync : 
  public wxPanel,
  public IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)>
{
public:
  // ...
  BEGIN_SINK_MAP(AutoSync)
    SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf001, OnItemAdd, &OnItemsAddInfo)
    SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf002, OnItemChange, &OnItemsChangeInfo)
    SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemsEvents), 0xf003, OnItemRemove, &OnItemsRemoveInfo)
  END_SINK_MAP()

  typedef IDispEventSimpleImpl<1, AutoSync, &__uuidof(Outlook::ItemsEvents)> ItemAddEvents;
  // ...
};

Попробуйте еще раз с этим упрощением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...