2010-05-14 13 views
0

Je souhaite créer un addin qui capture lorsqu'un {contact, calendrier, tâche, note} est {créé, modifié, supprimé}. J'ai le code suivant, pour le rendre plus court j'ai enlevé tout le code mais le lié au contact, puisque tous les types seront les mêmes je devine.Outlook Addin: exception DispEventAdvise

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)); 
} 

ailleurs défini:

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}; 

Les problèmes vient dans le

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)); 

Il donne exception 'atlbase.inl' lorsque la méthode exécute '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; 
} 

Je ne peux pas arriver à comprendre pourquoi. Toute suggestion ici? Tout semble aller bien, mais ce n'est évidemment pas le cas. Je suis coincé ici depuis assez longtemps. Besoin de votre aide, merci.

Répondre

0

Le premier fait d'un rapide coup d'oeil est que vous ne devez tirer d'une IDispEventSimpleImpl par interface - vous ne avez pas besoin pour chaque méthode dans l'interface:

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; 
    // ... 
}; 

Essayez à nouveau avec cette simplification.

+0

Simplification faite, mais toujours la même exception. Une autre idée? – framara

+0

@framara: Pas vraiment sans creuser un projet de test plus tard. Un tir aléatoire dans l'obscurité serait de tester avec le 'wxPanel' retiré. –

+0

wxPanel supprimé et ne fonctionne pas, toujours la même exception. Merci quand même, j'apprécie vraiment;) – framara

0

J'ai eu un problème similaire, la raison était que j'appelais des méthodes virtuelles à partir du constructeur. Si votre code est dans le constructeur, essayez de le déplacer vers FinalConstruct().

0

J'ai déjà rencontré cette exception, la suppression de ATL_NO_VTABLE peut résoudre ce problème.