【问题标题】:Can't access mail item in ATL/COM C++ Outlook Addin无法访问 ATL/COM C++ Outlook 插件中的邮件项目
【发布时间】:2017-05-04 11:05:09
【问题描述】:

当用户点击 Outlook 中的发送按钮时,我正在尝试获取邮件信息并根据值执行一些操作。因此我使用这个函数:

VOID WINAPI CConnect::ItemSend(IDispatch * Item, bool Cancel)

在我调用的 OnConnection 事件处理程序中

DispEventAdvise((IDispatch*)m_Application, &__uuidof(Outlook::ApplicationEvents));

在 Header-File 中是这样实现的:

public IDispEventSimpleImpl<1, CConnect, &__uuidof(Outlook::ItemEvents)>

public:

VOID WINAPI ItemSend(IDispatch * Item, bool Cancel);

BEGIN_SINK_MAP(CConnect)
SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemEvents), 0x0000F002, ItemSend, &fiMailItemEvents)
END_SINK_MAP()

这是正常工作的,但是在函数内部我尝试获取邮件项目时总是遇到异常。这是我访问该项目的代码:

CComPtr<Outlook::_MailItem> mail;
Item->QueryInterface(IID__MailItem, (void**)&mail);

我做错了什么?提前致谢

【问题讨论】:

  • HRESULT 的返回值是什么QueryInterface()
  • 不幸的是它没有返回任何东西,因为应用程序总是崩溃并出现错误'0xC000041D:在用户回调期间遇到未处理的异常'
  • QueryInterface() 返回一个 HRESULT,但是您没有检查它的值。只需像这样编辑您的代码:HRESULT hr = Item-&gt;QueryInterface(IID__MailItem, (void**)&amp;mail);。然后在下一行下一个断点,查看hr的值。
  • 它应该返回一个结果,但此时 Outlook 崩溃了,因此不会设置 HRESULT 值,也无法检索它。可能是物品有问题,但我不知道是什么原因造成的......
  • 您的事件处理程序可能有问题。你在课堂上实施IDispEventImplIDispEventSimpleImpl 吗?

标签: c++ outlook com outlook-addin atl


【解决方案1】:

您的代码中有几个注意事项,可能会导致问题:

  • 您的 ItemSend() 方法与 Outlook 类型库中的方法不同。应该声明为ItemSend(IDispatch* Item, VARIANT_BOOL* Cancel)
  • IDispEventSimpleImpl 模板声明中指向事件调度接口 IID 的指针指向 Outlook::ItemEvents。但是,您有兴趣处理来自Outlook::ApplicationEvents 的事件。
  • 虽然不是关键,但您对DispEventAdvise() 的调用会将应用程序接口指针转换为IDispatch*,而函数需要IUnknown* 参数。您也可以省略第二个参数。

以下类演示了如何相应地处理ItemSend 事件。由于您正在实现IDTExtensibility2 接口,因此您需要将初始化和清理例程分别移至其OnConnectionOnDisconnection 方法。

_ATL_FUNC_INFO fiMailItemEvents = { CC_STDCALL, VT_EMPTY, 2, { VT_DISPATCH, VT_BOOL | VT_BYREF } };

class CConect : 
    public ATL::IDispEventSimpleImpl<1, CConect, &(__uuidof(Outlook::ApplicationEvents))>
    {
public:
    CConect(Outlook::_ApplicationPtr piApp)
    {
        m_piApp = piApp;
        DispEventAdvise((IUnknown*)m_piApp);        
    }

    virtual ~CConect()
    {
        DispEventUnadvise((IUnknown*)m_piApp);
    }

    void __stdcall OnItemSend(IDispatch* Item, VARIANT_BOOL* Cancel)
    {
        CComPtr<Outlook::_MailItem> mail;
        HRESULT hr = Item->QueryInterface(__uuidof(Outlook::_MailItem), (void**)&mail);
    }

    BEGIN_SINK_MAP(CConect)
        SINK_ENTRY_INFO(1, __uuidof(Outlook::ApplicationEvents), 0x0000F002, OnItemSend, &fiMailItemEvents)     
    END_SINK_MAP()

private:

    Outlook::_ApplicationPtr m_piApp;
};

【讨论】:

  • 您的观点完全正确。我之前尝试使用 Outlook::ApplicationEvents,但无法正确解决,但感谢您的代码,它现在可以正常工作。非常感谢您的努力!
  • 很高兴听到。感谢您的反馈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 2011-03-20
  • 2015-11-05
  • 1970-01-01
相关资源
最近更新 更多