使用 VC++ 应用程序中的 VSTO 插件触发删除 Outlook 电子邮件附件

Trigger deletion of Outlook email attachment using VSTO AddIn from VC++ app

我正在尝试从 VC++ 应用程序中删除 Outlook 中的电子邮件。我有一个 Outlook 插件,它正在 Outlook 中加载并在系统中注册。触发电子邮件删除的 VC++ 应用成功调用 CoCreateInstance() 和 returns。

HRESULT hr;
IFoo* pISL;
CoInitialize(NULL);

LPOLESTR lpoleStr;
StringFromCLSID(__uuidof(Foo), &lpoleStr);

hr = CoCreateInstance(
    __uuidof(Foo),         // CLSID of coclass
    NULL,                    // not used - aggregation
    CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER,    // type of server
    __uuidof(IFoo),          // IID of interface
    (void**)&pISL);        // Pointer to our interface pointer

if (SUCCEEDED(hr))
{
    //fire event
    BSTR bstr = SysAllocString(params->szObjectPath);
    pISL->FooMethod(bstr);
    pISL->Release();
    SysFreeString(bstr);
}
else
{
    // Couldn't create the COM object. hr holds the error code.
}

CoUninitialize();

然后我使用返回的 COM 对象来调用我请求的 COM 接口中的方法。这些方法触发应由 Outlook 插件侦听的事件。

private void RegisterConnectionPoint()
{
    Logger.Log("RegisterConnectionPoint():");

    // Call QueryInterface for IConnectionPointContainer
    Foo foo = new Foo();
    IConnectionPointContainer icpc = (IConnectionPointContainer)foo;

    // Find the connection point for the
    // _IFoo source interface
    Guid IID_IFoo = typeof(_IFoo).GUID;

    icpc.FindConnectionPoint(ref IID_IFoo, out icp);

    // Pass a pointer of the host to the connection point
    icp.Advise(this, out cookie);
}

我的问题是 Outlook 插件从不接收来自 COM 对象的事件。我认为这可能是由于插件没有正确注册 COM 对象,或者有两个 COM 对象,一个用于 VC++ 应用程序,一个用于 Outlook 插件。

我的问题是

  1. 创建 Outlook VSTO 插件的基本概念是否可行,该插件在从 COM 服务器接收到事件时删除电子邮件,而 COM 服务器的事件是从单独的进程触发的?
  2. 如果第一个问题的答案是 'yes' 谁能看出我做错了什么?

调试 VC++ 应用程序端我得到这段代码,它似乎是生成的 ATL 代码(我没有编写所有代码,所以有时我在猜测):

int cConnections = m_vec.GetSize();

for (int iConnection = 0; iConnection < cConnections; iConnection++)
{
    pThis->Lock();
    CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
    pThis->Unlock();

    IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

    if (pConnection)
    {
        CComVariant avarParams[1];
        avarParams[0] = attachmentPath;
        avarParams[0].vt = VT_BSTR;
        CComVariant varResult;

        DISPPARAMS params = { avarParams, NULL, 1, 0 };
        hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
    }
}

问题是m_vec.GetSize() returns0。所以好像没有'connections'。这意味着我创建的 COM 对象实例与 Outlook 插件使用的实例不同,或者插件未正确注册。

所以@Dmitry 提供的 link 正是我所需要的。通过使用 运行 对象 Table (ROT),我能够获得对 Outlook 加载的 Outlook 插件的引用。所以允许我调用里面的方法来删除邮件附件。

需要进行一些更改,包括:

  1. 将加载项的注册移动到 ThisAddin_Startup() 作为默认 OutlookAddin class 使用静态构造函数,因此我无法在构造函数中引用加载项。
  2. 我还必须将我的代码移至用户会话进程,因为此 post 说明服务不支持从 ROT 检索 COM 对象。这只是我认为我应该补充的一点,因为它可能会阻碍人们尝试与我相同的事情。

此外,我发现这里 http://alax.info/blog/1444 的工具 ROT 查看器很有用,因为您可以检查您的插件是否真的注册到 ROT。

希望这对人们有所帮助。