4

Trying to use a COM visible .NET class via other .NET application and get exception:

Message: The object's type must be __ComObject or derived from __ComObject.

Parameter name: o

Stack Trace: at System.Runtime.InteropServices.Marshal.ReleaseComObject(Object o)

The class looks as follows:

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IViewer : IComInteropDefinedInterface
{
}

[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
[Guid("[some guid]")]
public class MyViewer : UserControl, IViewer    
{
    //IViewer implementation
}

I register the component with:

regasm [Assembly Path] /tlb /codebase

The client application, which is also in .NET instantiates successfully the given class, but when he callsMarshal.ReleaseComObject() it gets the exception described above.

Any idea for solving this problem?

EDIT: Unfortunately I can't provide the client application code for instantiating my object. However I know the client is using the same method to instantiate real COM objects.

Aaron
  • 2,236
  • 1
  • 16
  • 28
  • Can you include the code where your are instantiating the object and where you are calling `ReleaseComObject` too? What type has the object you are releasing? It seems that is it not a COM object. And as an aside: What is the reason that you want to use COM in this case? Using a .NET assembly from .NET works much easier without COM (and actually I have the suspicion that you are already doing so ;-) – Dirk Vollmar Aug 24 '10 at 08:27
  • Can you post the client code, it would be good to see how the component is being instantiated – Paul Nearney Aug 24 '10 at 08:28
  • Unfortunately I can't provide the client application code for instantiating my object. However I know the client is using the same method to instantiate real COM objects. – Aaron Aug 24 '10 at 08:51

4 Answers4

3

I got this problem recently, when reimplementing a native COM to managed code. The solution was to ask if the object is a native COM with Marshal.IsComObject, only native COMs must be release with Marshal.ReleaseComObject.

This is code:

if (Marshal.IsComObject(comObject))
{
     Marshal.ReleaseComObject(comObject);
}
comObject = null;

Important: you have to be sure, no use that object after been Released.

For a more detailed explanation read this post: http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx

mvega
  • 31
  • 3
  • That blog post is pretty specific about Marshal.IsComObject() **not** being the proper solution. – Hans Passant Jul 02 '13 at 21:32
  • That blog post says that the **Marshal.IsComObject() solution CAN be used if we are CERTAIN that the comObject IS NOT and WILL NEVER be used somewhere else** after it is released, even after a code refactoring... When unsure then it is better not releasing it at all (by hand) and let the garbage collector do it somewhen... – franckspike Oct 22 '14 at 14:25
0

But how are you creating the class instance? Simply using the expression new MyViewer() doesn't create a COM object. Instead it creates a plain old .Net object which cannot be used with the ReleaseComObject method.

Based on your sample code, in particular the line about MyViewer having an implementation, it doesn't sound like you're dealing with a COM object. Instead it looks like you have a managed object which implements a COM interface.

In order to use the ReleaseComObject you'd need to actually have a COM / RCW object.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • If the assembly containing `MyViewer` was added as a COM reference, wouldn't you rather get a COM object with `new MyViewer()` then (instead of a plain old .NET object)? I can't think of a reason why to do so but it *might* be possible. – Dirk Vollmar Aug 24 '10 at 08:35
  • @0xA3 yes if this type was a CoClass in a PIA (at least AFAIK). But in this case it's just a plain old managed object so new isn't doing anything special. – JaredPar Aug 24 '10 at 08:37
  • doesn't COM registered .NET class mean having an object that implements all the basic COM functionality including Release? – Aaron Aug 24 '10 at 11:05
  • @Aaron it depends on which part of the object. The .Net side doesn't have the Add/Release methods because it's simple not necessary on a .Net object. The CCW (COM callable wrapper) which is generated by the CLR will have them out of necessity. – JaredPar Aug 24 '10 at 15:32
0

My guess would be that you are actually not using COM but simply use a referenced .NET class. If your project contains code like

MyViewer viewer = new MyViewer();

and you have added the library containing MyViewer not as a COM reference, you are actually not using COM.

Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
0

I would rather try:

if (comObject != null)
{
      if (System.Runtime.InteropServices.Marshal.IsComObject(comObject))
      {                
          System.Runtime.InteropServices.Marshal.ReleaseComObject(comObject);
      }
      comObject= null;
}
Antonio
  • 307
  • 2
  • 11