Error while invoking the COM+ components developed using .Net (Serviced Components)

  • Thread starter Praveen Chandra
  • Start date
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
 
L

Luke Zhang [MSFT]

Hello Praveen,

After reading your message, I build a very simple test project in VS.NET
2005:

Project Type: Class Library

Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;


namespace COMTest
{
[GuidAttribute("65EA989D-DFCD-4D36-9E00-A9D928F8B9A2"),
ComVisible(true),ProgId("COMTest.Class1")]
public class Class1
{


public string GetHello(string name)
{
return "Hello, " + name;
}
}


}

Adn then strong name it, put the assemly in GAC and register it with
regasm.exe:

Regasm COMtest.DLL

And then, I create a windows form project with following code:


Type typ1 = Type.GetTypeFromProgID("COMTest.Class1");

Object obj = Activator.CreateInstance(typ1);
Object[] ArrArgs = new Object [1];

ArrArgs[0] = "Luke";

object r=typ1.InvokeMember("GetHello",
BindingFlags.InvokeMethod, null, obj, ArrArgs);

MessageBox.Show((string)r);


This work as expected on my side. So, compare with my test code, is there
any difference from yours? Especially, the ComVisible attribute and
registering with regasm.exe?

Regards,

Luke Zhang
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
P

Praveen Chandra

Hi Luke,

Thanks for your reply.

The sample which you have sent is working for non-servicedcomponent
application. But, what we are using are ServiceComponent. It is not working
for me.

The below is sample project which i made based on your sample to convert it
into ServicedComponent, when you try to invoke a method in this component
using .NET you will get the same error.
using System;
using System.Collections;
using System.Text;
using System.Runtime.InteropServices;
using System.EnterpriseServices;

namespace ABCTest
{
/// <summary>
/// Summary description for Class1.
/// </summary>
///
[GuidAttribute("FA25C241-EE0B-4cec-BE91-30119F116CF2"), ComVisible(true),
ProgId("ABCTest.Class1")]
public class Class1 : ServicedComponent
{
public Class1()
{
//
// TODO: Add constructor logic here
//
}
public string GetHello(string name)
{
return "Hello, " + name ;
}
}
}


Regards,

Praveen.
 
L

Luke Zhang [MSFT]

Hello Praveen,

I also test this with servicedcomponent :

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.EnterpriseServices;


namespace COMTest
{
[GuidAttribute("65EA989D-DFCD-4D36-9E00-A9D928F8B9A2"),
ComVisible(true),ProgId("COMTest.Class1")]
public class Class1 : ServicedComponent
{


public string GetHello(string name)
{
return "Hello, " + name;
}
}


}

After change the code, I re-compile the whole project, add the assembly in
GAC and register with regasm.exe. (Also generate a tlb file with
regasm.exe). And then, add a COM+ application and add the tlb file as a
components. When I test my client application, it still worked.

Is there any difference between our tests?

Luke Zhang
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
L

Luke Zhang [MSFT]

Hello Praveen,

Your sample works flawless on my side. I think there are some issues we may
check:

1. I changed the KEYFile to a .snk file generated by sn.exe.
2. When I create the COM+ application, I left all as default value: Create
an empty application->Server application->Interactive user - the current
logged on user ->...

Regards,

Luke Zhang
Microsoft Online Community Lead

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 

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

Similar Threads


Top