我正在开发一个旨在衡量Microsoft Outlook性能的项目。我的问题是“有没有办法检测发送/接收事件(开始和结束)?”。哪个API提供与此事件相关的方法。我一直在谷歌搜索一段时间,但我没有找到任何有趣的东西。
答案 0 :(得分:3)
使用Namespace.SyncObjects集合。
SyncObject.SyncStart / SyncEnd事件可能就是你想要的。
编辑:
只是拥有一个名为SyncStart
的方法绝对不会做任何事情。 Outlook如何知道它需要调用您的事件处理程序?
您需要订阅COM事件 - ATL和MFC都为COM事件提供包装器。在低级别,您将需要QI为IConnectionPointContainer引发事件(在您的情况下为SyncObject)的COM对象,调用IConnectionPointContainer::FindConnectionPoint
传递适当的disp接口GUID(SyncObjectEvents),然后调用IConnectionPoint.Advise
传递您对IDispatch
的实施。引发事件时,将使用与特定事件相对应的相应dispid调用IDispatch::Invoke()
的实现。
答案 1 :(得分:3)
正如Dimitry所说,您需要捕获SyncStart和SyncEnd事件,可能在C ++中执行此操作的最简单方法是为Outlook创建外接程序,获取正确的接口并实现接收器对象以获取所需的通知
http://msdn.microsoft.com/en-us/library/ee941475%28v=office.14%29.aspx
修改
不确定你是否设法让它工作,所以这里有一个没有插件的例子......
创建一个新的控制台应用程序,添加这些包含和导入(相应地更改路径)或使用相应的libid ......
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#import "C:\\Program Files (x86)\\Common Files\\microsoft shared\\OFFICE12\\mso.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids, auto_search rename("DocumentProperties", "MsoDocumentProperties") rename("RGB", "MsoRGB") exclude("IAccessible")
#import "C:\\Program Files (x86)\\Microsoft Office\\Office12\\msoutl.olb" raw_interfaces_only, raw_native_types, named_guids, auto_search rename("Folder", "OlkFolder") rename("CopyFile", "OlkCopyFile") rename("GetOrganizer", "GetOrganizerAE") rename("PlaySound", "OlkPlaySound") rename_namespace("Outlook")
现在创建一个接收事件的类......你只需要从IDispatch派生,我为一个事件添加了一个HANDLE,以便告知我们何时完成同步。
class COutlookEventSink : public IDispatch
{
public:
COutlookEventSink(HANDLE hEvent);
~COutlookEventSink(void);
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG STDMETHODCALLTYPE AddRef(void);
ULONG STDMETHODCALLTYPE Release(void);
// IDispatch
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(__RPC__out UINT *pctinfo);
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, __RPC__deref_out_opt ITypeInfo **ppTInfo);
HRESULT STDMETHODCALLTYPE GetIDsOfNames(
__RPC__in REFIID riid,
__RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
__RPC__in_range(0,16384) UINT cNames,
LCID lcid,
__RPC__out_ecount_full(cNames) DISPID *rgDispId);
HRESULT STDMETHODCALLTYPE Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr);
private:
long _lRef;
HANDLE _hEvent;
};
COutlookEventSink::COutlookEventSink(HANDLE hEvent)
{
_lRef = 0;
_hEvent = hEvent;
}
COutlookEventSink::~COutlookEventSink(void)
{
}
HRESULT STDMETHODCALLTYPE COutlookEventSink::QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
*ppvObject = NULL;
if(IsEqualGUID(riid, IID_IUnknown))
*ppvObject = reinterpret_cast<void**>(this);
if(IsEqualGUID(riid, IID_IDispatch))
*ppvObject = reinterpret_cast<void**>(this);
if(*ppvObject)
{
((IUnknown*)*ppvObject)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE COutlookEventSink::AddRef()
{
return InterlockedIncrement(&_lRef);
}
ULONG STDMETHODCALLTYPE COutlookEventSink::Release()
{
if (InterlockedDecrement(&_lRef) == 0)
{
delete this;
return 0;
}
return _lRef;
}
HRESULT STDMETHODCALLTYPE COutlookEventSink::GetTypeInfoCount(__RPC__out UINT *pctinfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE COutlookEventSink::GetTypeInfo(UINT iTInfo, LCID lcid, __RPC__deref_out_opt ITypeInfo **ppTInfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE COutlookEventSink::GetIDsOfNames(__RPC__in REFIID riid, __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames, __RPC__in_range(0,16384) UINT cNames, LCID lcid, __RPC__out_ecount_full(cNames) DISPID *rgDispId)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE COutlookEventSink::Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr)
{
switch(dispIdMember)
{
case 61441: // SyncStart - Start a Timer ?
break;
case 61444: // SyncEnd
SetEvent(_hEvent); // We done, exit
break;
}
return S_OK;
}
现在,在您的主要创建Outlook应用程序,并向SyncObjects添加接收器
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
CComPtr<Outlook::_Application> spApplication;
HRESULT hr = spApplication.CoCreateInstance(__uuidof(Outlook::Application), 0, CLSCTX_LOCAL_SERVER );
if(SUCCEEDED(hr) && spApplication)
{
CComPtr<Outlook::_NameSpace> spSession;
hr = spApplication->get_Session(reinterpret_cast<Outlook::_NameSpace **>(&spSession));
if (SUCCEEDED(hr) && spSession)
{
CComPtr<Outlook::SyncObjects> spSyncObjects;
hr = spSession->get_SyncObjects(reinterpret_cast<Outlook::SyncObjects **>(&spSyncObjects));
if (SUCCEEDED(hr) && spSyncObjects)
{
VARIANT index;
index.intVal = 1;
index.vt = VT_INT;
CComPtr<Outlook::_SyncObject> spSyncObject;
hr = spSyncObjects->Item(index, reinterpret_cast<Outlook::_SyncObject **>(&spSyncObject));
if (SUCCEEDED(hr) && spSyncObject)
{
CComPtr<IConnectionPointContainer> spContainer;
HRESULT hr = spSyncObject->QueryInterface(__uuidof(IConnectionPointContainer),reinterpret_cast<void **>(&spContainer));
if (SUCCEEDED(hr) && spContainer)
{
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
CComPtr<COutlookEventSink> spSink = new COutlookEventSink(hEvent);
CComPtr<IConnectionPoint> spConnectionPoint;
hr = spContainer->FindConnectionPoint(Outlook::DIID_SyncObjectEvents, &spConnectionPoint);
if (SUCCEEDED(hr) && spConnectionPoint)
{
DWORD dwCookie = 0;
CComPtr<IUnknown> spUnknown;
hr = spConnectionPoint->QueryInterface(IID_IUnknown, reinterpret_cast<void **>(&spUnknown));
if (SUCCEEDED(hr) && spUnknown)
{
hr = spConnectionPoint->Advise(spSink, &dwCookie);
if (SUCCEEDED(hr))
{
spSyncObject->Start(); // Syncronize
while(true)
{
MSG Message;
while(PeekMessage(&Message, NULL, WM_NULL, WM_NULL, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
DWORD dwStatus = WaitForSingleObject(hEvent, 0); // Wait for end
if(dwStatus == WAIT_OBJECT_0)
break;
}
spConnectionPoint->Unadvise(dwCookie);
}
}
}
}
}
}
}
spApplication.Release();
}
CoUninitialize();
return 0;
}
答案 2 :(得分:1)
我认为你需要的是获得两个展望事件之间的时间间隔。如果你打算用C ++做这件事,我认为这会有点麻烦。但是如果你想对任何MS office应用程序进行一些编程,MS提供了一个API调用宏(VBA)。
基本:
Macro是一个附加程序,您可以使用vb脚本编写,并且可以通过按钮单击或事件虎more details在任何MS office应用程序中运行。
因此,您可以通过打开Outlook打开宏编程界面,然后按ALT + F11。
使用这些宏可以做很多事情,你可以谷歌了解更多细节。
如果您需要向C ++应用程序获取一些信息,可以考虑从宏到C ++创建API,可能只是编写测试文件。
Here就是一个例子,你可以从中得到一些想法
Here是关于Macro的教程
希望这些想法可能有助于实现您的目标。