P
Praveen Chandra
Hi,
I just wanted to put down the issue with more detailed information so that
you can help us get to the right Microsoft resource for a solution! Here is
the problem description...
Our intent:
Accept the COM or COM+ class name, function-name and input parameter (fixed
string parameter) as string inputs and execute(invoke) the function at run
time.
Issue:
When the above discussed procedure is tried using the .Net code (pasted
below) we are getting the error: "Cannot load type (<COM ProgID>, <Assembly
Name>, Version=x.x.x.x, Culture=neutral, PublicKeyToken=xxxxxxxxx.". The
process works perfectly when COM/COM+ components (being invoked) are
developed either in VC++ or VB. Error is returned only for the COM+
components developed using .Net (Serviced Components).
Type typ1 = Type.GetTypeFromProgID(<COM ProgID>);
obj = Activator.CreateInstance(typ1);
Object[] ArrArgs = new Object [0];
typ1.InvokeMember(<Interface Method Name>, BindingFlags.InvokeMethod, null,
obj, ArrArgs);
We have also observed that the same component (.Net Serviced component)
works perfectly when invoked from VC++ or late-binding from VB. Code samples
used to test this process in VB and VC++ are pasted at the end of this
email.
What help we need?:
We need the .Net equivalent for the VC++ function code pasted below. This
function must work on all COM/COM+ component developed in any of the
programming languages, eg. VB, VC++ or .Net Serviced components.
VB:
Set obj = CreateObject(<COM ProgID>)
obj.<Interface Method Name>
Set obj = Nothing
VC++
STDMETHODIMP Invoke( BSTR bsClassName, BSTR bsFunctionName, BSTR bsInpXML,
VARIANT *vOutXML)
{
EXCEPINFO excepInfo;
DISPID dispid_msg;
DISPPARAMS dpDispMsg;
MULTI_QI mqi[1];
mqi[0].pItf = NULL;
IDispatch* pDispApp = NULL;
_variant_t vtResult;
VARIANT
vDispMsg[1];
VariantInit( &vDispMsg[0] );
START_ERROR_LOOKUP
CLSID clsid;
SAFE_CALL( CLSIDFromProgID( bsClassName, &clsid ) );
mqi[0].pIID = &IID_IUnknown;
mqi[0].hr = S_OK;
SAFE_CALL ( CoCreateInstanceEx( clsid, NULL,
CLSCTX_LOCAL_SERVER, NULL, 1, mqi ) );
SAFE_CALL( mqi[0].pItf->QueryInterface( IID_IDispatch,
(void**)&pDispApp ) );
vDispMsg[0].vt = VT_BSTR;
vDispMsg[0].bstrVal = _bstr_t(bsInpXML).copy();
dpDispMsg.cArgs = 1; //Total no of arguments to be passed
dpDispMsg.cNamedArgs = 0;
dpDispMsg.rgvarg = vDispMsg;
SAFE_CALL( pDispApp->GetIDsOfNames( IID_NULL,
&bsFunctionName, 1, LOCALE_USER_DEFAULT, &dispid_msg ) );
//Invoking a MTS method
SAFE_CALL( pDispApp->Invoke(dispid_msg, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&dpDispMsg, &vtResult, &excepInfo, NULL ) );
vOutXML->vt = VT_BSTR;
vOutXML->bstrVal = _bstr_t(vtResult).copy();
if( pDispApp != NULL ) pDispApp->Release();
if( mqi[0].pItf != NULL ) mqi[0].pItf->Release();
VariantClear ( &vDispMsg[0] );
START_ERROR_HANDLER
if( orchErr.GetErrorCode() == DISP_E_EXCEPTION )
orchErr.SetOrchErrorInfo( excepInfo );
// clearing
if( pDispApp != NULL ) pDispApp->Release();
if( mqi[0].pItf != NULL ) mqi[0].pItf->Release();
VariantClear ( &vDispMsg[0] );
END_ERROR_LOOKUP
return S_OK;
}
Thanks & Regards,
Praveen
I just wanted to put down the issue with more detailed information so that
you can help us get to the right Microsoft resource for a solution! Here is
the problem description...
Our intent:
Accept the COM or COM+ class name, function-name and input parameter (fixed
string parameter) as string inputs and execute(invoke) the function at run
time.
Issue:
When the above discussed procedure is tried using the .Net code (pasted
below) we are getting the error: "Cannot load type (<COM ProgID>, <Assembly
Name>, Version=x.x.x.x, Culture=neutral, PublicKeyToken=xxxxxxxxx.". The
process works perfectly when COM/COM+ components (being invoked) are
developed either in VC++ or VB. Error is returned only for the COM+
components developed using .Net (Serviced Components).
Type typ1 = Type.GetTypeFromProgID(<COM ProgID>);
obj = Activator.CreateInstance(typ1);
Object[] ArrArgs = new Object [0];
typ1.InvokeMember(<Interface Method Name>, BindingFlags.InvokeMethod, null,
obj, ArrArgs);
We have also observed that the same component (.Net Serviced component)
works perfectly when invoked from VC++ or late-binding from VB. Code samples
used to test this process in VB and VC++ are pasted at the end of this
email.
What help we need?:
We need the .Net equivalent for the VC++ function code pasted below. This
function must work on all COM/COM+ component developed in any of the
programming languages, eg. VB, VC++ or .Net Serviced components.
VB:
Set obj = CreateObject(<COM ProgID>)
obj.<Interface Method Name>
Set obj = Nothing
VC++
STDMETHODIMP Invoke( BSTR bsClassName, BSTR bsFunctionName, BSTR bsInpXML,
VARIANT *vOutXML)
{
EXCEPINFO excepInfo;
DISPID dispid_msg;
DISPPARAMS dpDispMsg;
MULTI_QI mqi[1];
mqi[0].pItf = NULL;
IDispatch* pDispApp = NULL;
_variant_t vtResult;
VARIANT
vDispMsg[1];
VariantInit( &vDispMsg[0] );
START_ERROR_LOOKUP
CLSID clsid;
SAFE_CALL( CLSIDFromProgID( bsClassName, &clsid ) );
mqi[0].pIID = &IID_IUnknown;
mqi[0].hr = S_OK;
SAFE_CALL ( CoCreateInstanceEx( clsid, NULL,
CLSCTX_LOCAL_SERVER, NULL, 1, mqi ) );
SAFE_CALL( mqi[0].pItf->QueryInterface( IID_IDispatch,
(void**)&pDispApp ) );
vDispMsg[0].vt = VT_BSTR;
vDispMsg[0].bstrVal = _bstr_t(bsInpXML).copy();
dpDispMsg.cArgs = 1; //Total no of arguments to be passed
dpDispMsg.cNamedArgs = 0;
dpDispMsg.rgvarg = vDispMsg;
SAFE_CALL( pDispApp->GetIDsOfNames( IID_NULL,
&bsFunctionName, 1, LOCALE_USER_DEFAULT, &dispid_msg ) );
//Invoking a MTS method
SAFE_CALL( pDispApp->Invoke(dispid_msg, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&dpDispMsg, &vtResult, &excepInfo, NULL ) );
vOutXML->vt = VT_BSTR;
vOutXML->bstrVal = _bstr_t(vtResult).copy();
if( pDispApp != NULL ) pDispApp->Release();
if( mqi[0].pItf != NULL ) mqi[0].pItf->Release();
VariantClear ( &vDispMsg[0] );
START_ERROR_HANDLER
if( orchErr.GetErrorCode() == DISP_E_EXCEPTION )
orchErr.SetOrchErrorInfo( excepInfo );
// clearing
if( pDispApp != NULL ) pDispApp->Release();
if( mqi[0].pItf != NULL ) mqi[0].pItf->Release();
VariantClear ( &vDispMsg[0] );
END_ERROR_LOOKUP
return S_OK;
}
Thanks & Regards,
Praveen