Problem with automating word

P

Phillip N Rounds

I'm trying to build an app ( VC++ 6 ) to automate word. The intent is to
have the user, from a menu within the app, initiate Word, write their
document, save it and quit. This app is to trap the word commands and
perform additional work in the background. I am basing my approach on
Microsoft's KB articles #238611, 196776, 183599 and 181745, particularly the
last two. I copied the code from these two KB articles. The only changes I
made to the code were to change the GUID of IWord11AppEvents to match the
GUID of the version of Word I have (
{000209FF-0000-0000-C000-000000000046} ).

The example program crashes at

// Find connection point for events you're interested in.
hr = pConnPtContainer->FindConnectionPoint( IID_IWord11AppEvents,
&m_pConnectionPoint );
ASSERT(!FAILED(hr));

I have a valid pConnPtContainer, so that isn't the problem.

My previous experience with automation is simple loading of data into excel,
so this is somewhat over my head. Any assistance would be appreciated.

Code is as follows:
// This is supposed to start Word, specify the events to catch, and point
these events to the CMySink class

void CMemoWriter::OnBUTTONStart()
{
// Check to see if you've already started the server.
if(m_app.m_lpDispatch != NULL) {
AfxMessageBox("Server already started.");
return;
}

char buf[256]; // General purpose buffer.

// Start Automation server.
COleException e;
if(!m_app.CreateDispatch("Word.Application.11", &e)) {
sprintf(buf, "Error on CreateDispatch(): %ld (%08lx)",
e.m_sc, e.m_sc);
AfxMessageBox(buf, MB_SETFOREGROUND);
return;

}

// Make server visible through automation.
// I.e.: Application.Visible = TRUE
DISPID dispID;
unsigned short *ucPtr;
BYTE *parmStr;
ucPtr = L"visible";
m_app.m_lpDispatch->GetIDsOfNames(
IID_NULL, &ucPtr, 1, LOCALE_USER_DEFAULT, &dispID
);
parmStr = (BYTE *)( VTS_VARIANT );
m_app.InvokeHelper(
dispID, DISPATCH_METHOD | DISPATCH_PROPERTYPUT, VT_EMPTY,
NULL, parmStr, &COleVariant((short)TRUE)
);

// Declare the events you want to catch.

// {000209FF-0000-0000-C000-000000000046}
static const GUID IID_IWord11AppEvents =
{0x000209FF,0x000,0x0000,{0xC0,0x00,0x0,0x00,0x00,0x00,0x00,0x46 } };

// Steps for setting up events.
// 1. Get server's IConnectionPointContainer interface.
// 2. Call IConnectionPointContainerFindConnectionPoint()
// to find the event you want to catch.
// 3. Call IConnectionPoint::Advise() with the IUnknown
// interface of your implementation of the events.

HRESULT hr;

// Get server's IConnectionPointContainer interface.
IConnectionPointContainer *pConnPtContainer;
hr = m_app.m_lpDispatch->QueryInterface(
IID_IConnectionPointContainer,
(void **)&pConnPtContainer
);
ASSERT(!FAILED(hr));


IEnumConnectionPoints* ppEnum;
// HRESULT hr2 = pConnPtContainer->EnumConnectionPoints( &ppEnum );

// Find connection point for events you're interested in.
hr = pConnPtContainer->FindConnectionPoint(
IID_IWord11AppEvents,
&m_pConnectionPoint
);
ASSERT(!FAILED(hr));

// Get the IUnknown interface of your event implementation.
LPUNKNOWN pUnk = m_myEventSink.GetInterface(&IID_IUnknown);
ASSERT(pUnk);

// Setup advisory connection!
hr = m_pConnectionPoint->Advise(pUnk, &m_adviseCookie);
ASSERT(!FAILED(hr));

// Release IConnectionPointContainer interface.
pConnPtContainer->Release();


}

Here is the MySink Class

#include "stdafx.h"
#include "RFQ Distributer.h"
#include "MyEventSink.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// MyEventSink

IMPLEMENT_DYNCREATE(MyEventSink, CCmdTarget)

MyEventSink::MyEventSink()
{
EnableAutomation();
}

MyEventSink::~MyEventSink()
{
}


void MyEventSink::OnFinalRelease()
{
// When the last reference for an automation object is released
// OnFinalRelease is called. The base class will automatically
// deletes the object. Add additional cleanup required for your
// object before calling the base class.

CCmdTarget::OnFinalRelease();
}


BEGIN_MESSAGE_MAP(MyEventSink, CCmdTarget)
//{{AFX_MSG_MAP(MyEventSink)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BEGIN_DISPATCH_MAP(MyEventSink, CCmdTarget)
//{{AFX_DISPATCH_MAP(MyEventSink)
DISP_FUNCTION(MyEventSink, "Startup", Startup, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(MyEventSink, "Quit", Quit, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(MyEventSink, "DocumentChange", DocumentChange, VT_EMPTY,
VTS_NONE)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()

// Note: we add support for IID_IMyEventSink to support typesafe binding
// from VBA. This IID must match the GUID that is attached to the
// dispinterface in the .ODL file.

// {FD6BB110-2541-474D-88F5-D64061846531}
static const IID IID_IMyEventSink =
{ 0x000209ff, 0x000, 0x000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46 } };

BEGIN_INTERFACE_MAP(MyEventSink, CCmdTarget)
INTERFACE_PART(MyEventSink, IID_IMyEventSink, Dispatch)
END_INTERFACE_MAP()

/////////////////////////////////////////////////////////////////////////////
// MyEventSink message handlers

void MyEventSink::Startup()
{
::AfxMessageBox("WOrd Started");

}

void MyEventSink::Quit()
{
::AfxMessageBox("Word QUit");

}

void MyEventSink::DocumentChange()
{
::AfxMessageBox("Document Change");

}
 
C

Cindy M -WordMVP-

Hi Phillip,
The only changes I
made to the code were to change the GUID of IWord11AppEvents to match the
GUID of the version of Word I have (
{000209FF-0000-0000-C000-000000000046} ).
And which version of Word would that be?

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 8 2004)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or
reply in the newsgroup and not by e-mail :)
 
P

Phillip N Rounds

Cindy M -WordMVP- said:
Hi Phillip,

And which version of Word would that be?

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 8 2004)


This reply is posted in the Newsgroup; please post any follow question or
reply in the newsgroup and not by e-mail :)

Another thing I fogot is that

hr = pConnPtContainer->FindConnectionPoint( IID_IWord11AppEvents,
&m_pConnectionPoint );


returns hr = -2147220992, and I haven't been able to find the error code
that that represents ( It's not in winerr.h, nor does ErrorLookup translate
the error code)
 
C

Cindy M -WordMVP-

Hi Phillip,
returns hr = -2147220992, and I haven't been able to find the error code
that that represents ( It's not in winerr.h, nor does ErrorLookup translate
the error code)
This looks a lot like a Word internal automation error, and these aren't
documented, as far as I know.

I'm afraid I can't help you with this.

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 8 2004)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or
reply in the newsgroup and not by e-mail :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top