Как прослушивать события COM от приложений Office, которые были запущены независимо?

Что я хочу сделать:

Написать приложение, которое прослушивает события Office. Я хочу слушать события из любого экземпляра, открытого на машине. Например, если я слушаю BeforeDocumentSave в Word, я хочу, чтобы мой приемник для этого метода активировался всякий раз, когда любой экземпляр Word на хосте сохраняет документ.

Еще одно требование - я пишу на C ++ без MFC или ATL.

Что я сделал:

Я ' Я написал программу, которая должна прослушивать события Word. См. Код ниже.

Проблема:

Это не работает - обработчики событий никогда не вводятся, хотя я открываю приложение Word и выполняю действия, которые должны запускать события.

У меня есть некоторые конкретные вопросы, и, конечно, приветствуется любой другой ввод!

Вопросы:

  1. Можно ли прослушивать события из приложения, которое было запущено не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.

  2. В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:

Однако большинство событий, таких как t работают - обработчики событий никогда не вводятся, хотя я открываю приложение Word и выполняю действия, которые должны запускать события.

У меня есть некоторые конкретные вопросы, и, конечно, любой другой ввод будет очень приветствоваться!

Вопросы :

  1. Можно ли прослушивать события из приложения, которое было запущено не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.

  2. В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:

Однако большинство событий, таких как t работают - обработчики событий никогда не вводятся, хотя я открываю приложение Word и выполняю действия, которые должны запускать события.

У меня есть некоторые конкретные вопросы, и, конечно, любой другой ввод будет очень приветствоваться!

Вопросы :

  1. Можно ли прослушивать события из приложения, которое было запущено не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.

  2. В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:

Однако большинство событий, таких как

  1. Можно ли прослушивать события из приложения, запущенного не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.

  2. В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:

Однако большинство событий, таких как

  1. Можно ли прослушивать события из приложения, запущенного не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.

  2. В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:

Однако большинство событий, таких как События книги Microsoft Excel, делать не запускать с DISPID 1. В таком случаях вы должны явно изменить отправить карту в MyEventSink.cpp в сопоставьте DISPID с правильными methods.

How do I modify the dispatch map?

  1. For now I've defined only Startup, Quit and DocumentChange, which take no arguments. The methods I really need do take arguments, specifically one of type Document. How do I define parameters of this type if I'm not using MFC?

Code:

Here's the header file for my project, followed by the C file:

#ifndef _OFFICEEVENTHANDLER_H_
#define _OFFICEEVENTHANDLER_H_

// 000209FE-0000-0000-C000-000000000046
static const GUID IID_IApplicationEvents2 =  
{0x000209FE,0x0000,0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};

struct IApplicationEvents2 : public IDispatch // Pretty much copied from typelib
{
/*
 * IDispatch methods
 */
STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj) = 0; 
STDMETHODIMP_(ULONG) AddRef()  = 0;  
STDMETHODIMP_(ULONG) Release() = 0;

STDMETHODIMP GetTypeInfoCount(UINT *iTInfo) = 0;
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) = 0;
STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, 
                              UINT cNames,  LCID lcid, DISPID *rgDispId) = 0;
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
                              WORD wFlags, DISPPARAMS* pDispParams,
                              VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
                              UINT* puArgErr) = 0;

/*
 * IApplicationEvents2 methods
 */
STDMETHODIMP Startup();
STDMETHODIMP Quit();
STDMETHODIMP DocumentChange();
};


class COfficeEventHandler : IApplicationEvents2
{

public:
DWORD                        m_dwEventCookie;

COfficeEventHandler
(
) :
m_cRef(1),
m_dwEventCookie(0)
{
}

STDMETHOD_(ULONG, AddRef)()
{
InterlockedIncrement(&m_cRef);

return m_cRef;  
}

STDMETHOD_(ULONG, Release)()
{
InterlockedDecrement(&m_cRef);

if (m_cRef == 0)
{
    delete this;
    return 0;
}

return m_cRef;
}

STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj)
{
 if (riid == IID_IUnknown){
    *ppvObj = static_cast<IApplicationEvents2*>(this);
}

else if (riid == IID_IApplicationEvents2){
    *ppvObj = static_cast<IApplicationEvents2*>(this);
}
else if (riid == IID_IDispatch){
    *ppvObj = static_cast<IApplicationEvents2*>(this);
}

else
{
    char clsidStr[256];
    WCHAR wClsidStr[256];
    char txt[512];

    StringFromGUID2(riid, (LPOLESTR)&wClsidStr, 256);

    // Convert down to ANSI
    WideCharToMultiByte(CP_ACP, 0, wClsidStr, -1, clsidStr, 256, NULL, NULL);

    sprintf_s(txt, 512, "riid is : %s: Unsupported Interface", clsidStr);

    *ppvObj = NULL;
    return E_NOINTERFACE;
}

static_cast<IUnknown*>(*ppvObj)->AddRef();

return S_OK;
}

STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
return E_NOTIMPL;
}

STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return E_NOTIMPL;
}

STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
       LCID lcid, DISPID* rgdispid)
{
return E_NOTIMPL;
}

STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
       LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
       EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
return E_NOTIMPL;
}

// IApplicationEvents2 methods
void Startup();
void Quit();
void DocumentChange();


protected:
LONG                        m_cRef;
};

#endif // _OFFICEEVENTHANDLER_H_

The C file:

#include <windows.h>
#include <stdio.h>
#include "OfficeEventHandler.h"
#include "OCIdl.h"



int main()
{
CLSID clsid;                   // CLSID of automation object 
HRESULT hr; 
LPUNKNOWN punk = NULL;         // IUnknown of automation object 
LPDISPATCH pdisp = NULL;       // IDispatch of automation object 
IConnectionPointContainer *pConnPntCont;
IConnectionPoint *pConnPoint;
IUnknown *iu;
IID id;  
COfficeEventHandler *officeEventHandler = new COfficeEventHandler;

CoInitialize(NULL);

hr = CLSIDFromProgID(OLESTR("Word.Application"), &clsid); 

hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER,  
                      IID_IUnknown, (void FAR* FAR*)&punk); 

hr = punk->QueryInterface(IID_IConnectionPointContainer, (void FAR* FAR*)&pConnPntCont); 

// IID for ApplicationEvents2 
hr = IIDFromString(L"{000209FE-0000-0000-C000-000000000046}",&id);

hr = pConnPntCont->FindConnectionPoint( id, &pConnPoint );

hr = officeEventHandler->QueryInterface( IID_IUnknown, (void FAR* FAR*)&iu);

hr = pConnPoint->Advise( iu, &officeEventHandler->m_dwEventCookie );

Sleep( 360000 );

hr = pConnPoint->Unadvise( officeEventHandler->m_dwEventCookie );
if (punk) punk->Release(); 
if (pdisp) pdisp->Release(); 

CoUninitialize();

return hr; 
}

// IApplicationEvents2 methods
void COfficeEventHandler::Startup()
{
printf( "In Startup\n" );
}

void COfficeEventHandler::Quit()
{
printf( "In Quit\n" );
}

void COfficeEventHandler::DocumentChange()
{
printf( "In DocumentChnage\n" );
}
5
задан Alexis Pigeon 25 July 2013 в 19:09
поделиться