计算发送/接收持续时间 - Outlook

时间:2013-09-03 15:52:47

标签: c++ api outlook

我正在开发一个旨在衡量Microsoft Outlook性能的项目。我的问题是“有没有办法检测发送/接收事件(开始和结束)?”。哪个API提供与此事件相关的方法。我一直在谷歌搜索一段时间,但我没有找到任何有趣的东西。

3 个答案:

答案 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)。

基本:

  1. Macro是一个附加程序,您可以使用vb脚本编写,并且可以通过按钮单击或事件虎more details在任何MS office应用程序中运行。

  2. 因此,您可以通过打开Outlook打开宏编程界面,然后按ALT + F11。

  3. 使用这些宏可以做很多事情,你可以谷歌了解更多细节。

  4. 如果您需要向C ++应用程序获取一些信息,可以考虑从宏到C ++创建API,可能只是编写测试文件。

  5. Here就是一个例子,你可以从中得到一些想法

  6. Here是关于Macro的教程

  7. 希望这些想法可能有助于实现您的目标。