C++ MAPI开发Outlook插件删除会议附件后未刷新,OOM调用Remove报错
MAPI删除附件界面未刷新原因
- 底层MAPI接口
IMessage::DeleteAttach只会修改邮件/会议项的存储层数据,不会主动通知Outlook UI层触发缓存更新。Outlook对当前打开的编辑项会在内存中缓存完整的属性快照,包括附件列表,只有强制重新加载项、重启Outlook时才会从存储层拉取最新数据,所以会出现实际已删除但界面仍显示的问题。 - 额外注意:如果操作完成后没有调用
IMAPIProp::SaveChanges带上KEEP_OPEN_READWRITE标记,部分修改可能没有正确同步到缓存关联的对象实例,也会导致该问题。
对应解决方法
操作完MAPI删除逻辑后,先调用SaveChanges确保修改落地,再调用OOM接口的_AppointmentItem::Save()保存对象,最后调用当前Inspector的Refresh()方法即可触发界面即时刷新。
OOM调用
Remove抛异常原因 你的代码存在一个核心问题:作为Outlook进程内运行的插件,不应该通过CoCreateInstance重新创建Outlook.Application实例,你创建的是跨进程的Outlook实例,访问当前进程内正在编辑的会议项时会触发权限校验、对象状态不一致问题,这是Remove调用抛异常的最常见原因。
其他可能的原因:
- 没有校验
myattachments指针的有效性,获取Attachments集合失败时直接调用方法会触发空指针异常 - 发送事件回调中Outlook已经将会议项置为只读状态,不允许修改附件
- 索引对应的附件是嵌入式OLE对象、签名关联附件等特殊类型,直接删除触发内部错误
对应解决方法
- 替换你自己创建的
pOlkApp实例,直接使用插件初始化时OnConnection回调拿到的进程内_Application接口指针,规避跨进程调用的权限问题 - 调用
Remove前增加myattachments空指针校验,删除后调用spAppointmentItem->Save()保存修改,再调用pInsp->Refresh()刷新界面 - 若仍存在异常,捕获异常获取对应的HRESULT值,进一步定位是权限、无效索引还是对象状态错误
问题相关代码
CLSID clsidOutlook; hr = CLSIDFromProgID(L"Outlook.Application", &clsidOutlook); Olk::_ApplicationPtr pOlkApp; hr = CoCreateInstance(clsidOutlook, NULL, CLSCTX_LOCAL_SERVER, Olk::IID__Application, reinterpret_cast<void **>(&(pOlkApp))); Olk::_InspectorPtr pInsp = pOlkApp->ActiveInspector(); if (NULL == pInsp) { LOG(_T("Failed to obtain Inspector")); return S_FALSE; } IDispatchPtr dispItem = pInsp->GetCurrentItem(); if (NULL == dispItem) { LOG(_T("Failed to obtain Inspector")); return S_FALSE; } CComQIPtr<Olk::_AppointmentItem> spAppointmentItem = dispItem; if (spAppointmentItem) { auto myattachments = spAppointmentItem->Attachments; if (myattachments->Count > 0) { myattachments->Remove(1); //此处抛出错误 } }
内容的提问来源于stack exchange,提问作者Mahesh Amarelia
相关产品推荐
相关产品推荐

