1

I am trying to access C# objects from another process than the one where they reside via COM. The C# objects are exposed to COM.

The problem is that when I call a method on those objects, the calls are executed loccally, not on the outproc COM server where I want the side effects of these calls to happen.

More precisely, here is what I do in the process trying to access the objects residing in the outproc COM server:

Type oType = Type.GetTypeFromProgID("myProgId");

var obj = Activator.CreateInstance(oType);

var result = oType.InvokeMember("GetObjForMyClassMethod",
                                BindingFlags.InvokeMethod, null, obj, null);

Then I cast result into the appropriate interface (IMyInterface) of the C# class and when I make calls on methods of that interface they are executed remotely on the outproc COM server just like I expect.

The problem starts when I use that interface to retrieve other C# objects (I use a method IMyInterface.GetOtherObject() that returns IOtherObjectInterface).

When I make calls on IOtherObjectInterface, they are executed locally, not on the outproc COM server so their side effects are lost (e.g if I call a SetValue method, the value doesn't arrive on the outproc server and it is lost).

Furthermore when I look under the debugger at runtime I see that the type of the interface for which the remote calls work is System._ComObject whereas the type for the interface where the remote calls don't work is the actual type (IOtherObjectInterface).

I've tried to replicate everything (all the attributes and other interfaces implemented) about the way IMyInterface (the one for which remote calls work) is exposed to COM on IOtherObjectInterface (the one for which remote calls don't work) but no luck.

What must done so that the calls I make on IOtherObjectInterface are executed in the outproc server via RPC, not in the local process (the one where the calls are issued) where they are no use to anybody?

EDIT:

I have since found out that if I retrieve the object for which it doesn't work (IOtherObjectInterface) using the same method that I use for the object for which it works ( oType.InvokeMember("GetOtherObjForMyClassMethod",....) it still doesn't work (the calls I make on the object are still not forwarded to the outproc COM server).

So the problem is with the class itself, not the method used to retrieve the objects.

I strongly suspect that this problem is somehow related to serialization even though both classes (working and not working) seem to implement serialization the same way...

EDIT2:

The part I don't get is the fact that the class for which this "COM remoting" works (the one for which I get System._ComObject when I retrieve the object outside the COM server) has the attribute "serializable". I thought the default for types with this attribute was marshal-by-value.

mnrtyrpt123
  • 143
  • 2
  • 10
  • Note: I found out this is not a DCOM question, processes run on the same machine. – Hans Passant Sep 11 '12 at 12:33
  • `I thought the default for types with this attribute was marshal-by-value.` - Yes, but you are not marshaling this instance (it lives in the OOP COM server process), you are talking to its `__ComObject` proxy created by the CLR. – Chris Dickson Sep 14 '12 at 09:21

3 Answers3

0

You need to use a ServicedComponent as per Marc's answer here:

Create Out-Of-Process COM in C#/.Net?

Community
  • 1
  • 1
Slugart
  • 4,535
  • 24
  • 32
  • It says it is one option. Like I explained above it works for one class (without using ServicedComponent) but not the other but I cannot figure out the difference between the two that make it work in one case and not the other... – mnrtyrpt123 Sep 11 '12 at 11:35
0

What you could do is create a new Application in the Component Services console, and declare it's an out-of-process application. For this, you'll need to

  1. Create an new Application
  2. Right click on this application
  3. Go to the "Activation" tab, and select "Server Application"
  4. Add your DLL to this application

You may have to configure the security.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Like I said it works for one class and not the other. So the problem is not with the configuration of the application hosting these 2 classes (otherwise it would not work at all). – mnrtyrpt123 Sep 11 '12 at 14:31
0

You have confirmed, I think, that IMyInterface.GetOtherObject() executes remotely, and your question is why the object returned to your calling code is a concrete instance of the .NET type implementing IOtherObjectInterface, rather than being a System._ComObject or something else which would cause method calls on that object to be remoted.

The answer must be that IMyInterface.GetOtherObject() instantiates the "OtherObject" and then when it returns, that instance is being marshalled to your calling process. This will happen by default if the object is of a serializable .NET type.

I think that if the object were a MarshalByRefObject, it wouldn't be marshalled back to the calling process: the calling code would receive instead a TransparentProxy and then calls on it would be remoted as you expect.

The original (IMyInterface) object is a special case because the calling code itself instantiates this, using the Activator and a Type derived from the ProgID, with the assistance (under the hood) of the COM Runtime, resulting in the special proxy type _ComObject.

Chris Dickson
  • 11,964
  • 1
  • 39
  • 60
  • first of all, thanks for understanding my question ;-) I thought about MarshalByRefObject but I think that implies using remoting and my understanding is that this technology is more or less obsolete...I may have to use that solution as a last resort. – mnrtyrpt123 Sep 12 '12 at 11:49
  • Well, `System.__ComObject` is derived from MarshalByRefObject, so you are using it already. I think your worry that you would be using some obsolete remoting technology is unfounded. Remoting per se is deprecated in favour of WCF for implementing IPC, but the underlying plumbing is there in the CLR and fundamental to COM Interop and WCF. – Chris Dickson Sep 12 '12 at 12:25
  • The point is that I'd like to keep using MarshalByRefObject via System._ComObject. – mnrtyrpt123 Sep 14 '12 at 08:49