我正在尝试从 VC++ 应用程序中删除 Outlook 中的电子邮件。我有一个 Outlook 插件,它正在 Outlook 中加载并在系统中注册。触发电子邮件删除的 VC++ 应用程序调用 CoCreateInstance() 并成功返回。
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 接口(interface)中的方法。这些方法触发应由 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 插件。
我的问题是
- 创建 Outlook VSTO 插件的基本概念是否可行,该插件在从 COM 服务器接收事件时删除电子邮件,而 COM 服务器的事件是从单独的进程触发的?
- 如果第一个问题的答案是"is",那么任何人都可以看到我做错了什么吗?
调试 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, ¶ms, &varResult, NULL, NULL);
}
}
问题是 m_vec.GetSize() 返回 0。所以似乎没有“连接”。这意味着我创建的 COM 对象实例与 Outlook 插件使用的实例不同,或者插件未正确注册。
最佳答案
所以@Dmitry 提供的链接正是我所需要的。通过使用运行对象表 (ROT),我能够获得对 Outlook 加载的 Outlook 插件的引用。因此允许我调用其中的方法来删除邮件附件。
需要进行一些更改,包括:
- 将加载项的注册移动到 ThisAddin_Startup() 作为默认 OutlookAddin 类使用静态构造函数,因此我无法在构造函数中引用加载项。
- 我还必须将我的代码移动到用户 session 进程,因为这篇文章 COMException (0x800401E3): Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE)) with scheduled task说明服务不支持从 ROT 检索 COM 对象。这只是我认为我应该补充的一点,因为它可能会阻碍人们尝试与我相同的事情。
此外,我在此处找到了 ROT 查看器工具 http://alax.info/blog/1444很有用,因为您可以检查您的插件是否真的注册到 ROT。
希望这对人们有所帮助。
关于c++ - 从 VC++ 应用程序使用 VSTO 插件触发删除 Outlook 电子邮件附件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40999843/