swh062500
asked on
Writing an OLE Automation Container with VC++
I want to access a simple OLE Automation Server I wrote in VB, but I can't get it working. Ok, I am a relative newbie to OLE programming with VC++, but I think I did everything as described in the books (Brockschmidt etc.), but no.
Anyway, here's what I am doing. I'd be very grateful if anybody has an idea what's wrong.
I first initialize OLE, create the object, get its IDispatch interface and the DISPID for a property called 'Color' with the following statements:
CoInitialize(NULL);
hr=::CLSIDFromProgID(T2COL E(_T("Layo utServer.L ayout")),
&CLSID_LayoutServer);
hr = CoCreateInstance(CLSID_Lay outServer, NULL, CLSCTX_LOCAL_SERVER,
IID_IDispatch, (LPVOID*)&m_pIDispatch);
hr = NameToID(T2OLE(_T("Color") ), &m_DILayoutColor);
This seems to work fine (hr is always 0, I deleted these checks here to save some space). The variables used are defined as follows:
IDispatch* m_pIDispatch; //Interface we use
DISPID m_DILayoutColor; //long (I4) Prop
CLSID CLSID_LayoutServer;
The NameToID function is just a wrapper around GetIDsOfNames without all the parameters of that function to retrieve DISPID's more easily:
HRESULT CLayoutClientDlg::NameToID (OLECHAR* pszName, DISPID* pDispID)
{
HRESULT hr;
hr = m_pIDispatch->GetIDsOfName s(IID_NULL , &pszName, 1,
LOCALE_SYSTEM_DEFAULT, pDispID);
return hr;
}
Now I should be able to get and put the value of this property. I have the following variables to provide the necessary parameters to Invoke:
HRESULT hr;
DISPPARAMS dp;
VARIANTARG va;
EXCEPINFO ei;
unsigned int uArgErr;
Also two macros to facilitate the setting of parameters:
#define SETDISPPARAMS(dp, numArgs, pvArgs, numNamed, pNamed) \
{\
(dp).cArgs=numArgs;\
(dp).rgvarg=pvArgs;\
(dp).cNamedArgs=numNamed;\
(dp).rgdispidNamedArgs=pNa med;\
}
#define SETNOPARAMS(dp) SETDISPPARAMS(dp, 0, NULL, 0, NULL)
To get the value of the color property, I know call Invoke as follows:
SETNOPARAMS(dp);
hr = m_pIDispatch->Invoke(m_DIL ayoutColor , IID_NULL,
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, &va, &ei, &uArgErr);
But, the application crashes with an error message "No handle exception in LayoutClient.exe (Oleaut32.dll): 0xC0000005 Access violation" (this is only a translation
of the original japanese message, so it might look somewhat different on an English system). Why?
Setting the property as follows:
va.vt = VT_I4;
va.lVal = 255L;
SETDISPPARAMS(dp, 1, &va, 0, NULL);
hr = m_pIDispatch->Invoke(m_DIL ayoutColor , IID_NULL,
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, &va, &ei, &uArgErr);
This produces no error (hr=0), but it doesn't set the value correctly. If I have a VB client reading the value, it is not 255 (some other, non-constant value). 2 VB clients can exchange data this way (one client setting, one reading).
Any help appreciated, thanks.
-Stephan
Anyway, here's what I am doing. I'd be very grateful if anybody has an idea what's wrong.
I first initialize OLE, create the object, get its IDispatch interface and the DISPID for a property called 'Color' with the following statements:
CoInitialize(NULL);
hr=::CLSIDFromProgID(T2COL
&CLSID_LayoutServer);
hr = CoCreateInstance(CLSID_Lay
IID_IDispatch, (LPVOID*)&m_pIDispatch);
hr = NameToID(T2OLE(_T("Color")
This seems to work fine (hr is always 0, I deleted these checks here to save some space). The variables used are defined as follows:
IDispatch* m_pIDispatch; //Interface we use
DISPID m_DILayoutColor; //long (I4) Prop
CLSID CLSID_LayoutServer;
The NameToID function is just a wrapper around GetIDsOfNames without all the parameters of that function to retrieve DISPID's more easily:
HRESULT CLayoutClientDlg::NameToID
{
HRESULT hr;
hr = m_pIDispatch->GetIDsOfName
LOCALE_SYSTEM_DEFAULT, pDispID);
return hr;
}
Now I should be able to get and put the value of this property. I have the following variables to provide the necessary parameters to Invoke:
HRESULT hr;
DISPPARAMS dp;
VARIANTARG va;
EXCEPINFO ei;
unsigned int uArgErr;
Also two macros to facilitate the setting of parameters:
#define SETDISPPARAMS(dp, numArgs, pvArgs, numNamed, pNamed) \
{\
(dp).cArgs=numArgs;\
(dp).rgvarg=pvArgs;\
(dp).cNamedArgs=numNamed;\
(dp).rgdispidNamedArgs=pNa
}
#define SETNOPARAMS(dp) SETDISPPARAMS(dp, 0, NULL, 0, NULL)
To get the value of the color property, I know call Invoke as follows:
SETNOPARAMS(dp);
hr = m_pIDispatch->Invoke(m_DIL
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, &va, &ei, &uArgErr);
But, the application crashes with an error message "No handle exception in LayoutClient.exe (Oleaut32.dll): 0xC0000005 Access violation" (this is only a translation
of the original japanese message, so it might look somewhat different on an English system). Why?
Setting the property as follows:
va.vt = VT_I4;
va.lVal = 255L;
SETDISPPARAMS(dp, 1, &va, 0, NULL);
hr = m_pIDispatch->Invoke(m_DIL
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, &va, &ei, &uArgErr);
This produces no error (hr=0), but it doesn't set the value correctly. If I have a VB client reading the value, it is not 255 (some other, non-constant value). 2 VB clients can exchange data this way (one client setting, one reading).
Any help appreciated, thanks.
-Stephan
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.