RegisterAssembly, CreateComInstanceFrom and IsCOMObject

  • Thread starter Thread starter Corey Alix
  • Start date Start date
C

Corey Alix

I am registering a managed class as a COM class via
RegistrationServices.RegisterAssembly, then I am instantiating that class
via CreateObject, then I am testing if the object is a COM instance via
Type.IsCOMObject. Surprisingly (to me) the return value is False.

This is a problem for me, because I am using managed code to write a OWC
spreadsheet addin, and memory allocated by the addin is not freed when the
spreadsheet is destroyed. I wanted to explicitly invoke
InteropServices.Marshal.ReleaseComObject, but it is failing, presumably
because the object returned by CreateObject() is, in some way, not a COM
class.

Can anyone explain why the IsCOMObject is returning False, and what I might
be able to do to make it return True?

Sub Main()
Dim lvType As System.Type = GetType(ComClassTest)
Dim lvRegistrationServices As New
Runtime.InteropServices.RegistrationServices()
lvRegistrationServices.RegisterAssembly(lvType.Assembly,
Runtime.InteropServices.AssemblyRegistrationFlags.None)
Runtime.InteropServices.RegistrationConnectionType.SingleUse)
Try
Dim lvObject As System.Object =
Microsoft.VisualBasic.CreateObject(lvRegistrationServices.GetProgIdForType(lvType))
Debug.Assert(True = lvObject.GetType.IsCOMObject, "CreateObject
creates a COM object") ' this assertion fails
Finally
lvRegistrationServices.UnregisterAssembly(lvType.Assembly)
End Try
End Sub
 
Corey,
Can anyone explain why the IsCOMObject is returning False, and what I might
be able to do to make it return True?

When two .NET objects communicate in the same process you don't go
through COM interop, so you don't have an RCW reference and therefore
IsCOMObject is false.

Why do you think ReleaseComObject could help you here? The garbage
collector is responsible for cleaning up mamanged resources.


Mattias
 
Mattias,
Why do you think ReleaseComObject could help you here? The garbage
collector is responsible for cleaning up managed resources.

I may be going about this the wrong way, but here's the explanation of what
lead me to where I am. I'm sorry that it is so long, but it boils down to
this question:

Is it possible to make a .NET class appear as a COM class inside of .NET so
that ReleaseComObject would actually work?

Using ReleaseComObject was a suggestion from a respected source in another
newsgroup (microsoft.public.office.developer.web.components). I'm using the
Microsoft Office Web Components (OWC10) spreadsheet control. That control
has an AddIn method which expects a COM Automation addin object, which is
just an instance of a COM class. Once registered via AddIn, the methods may
be used in spreadsheet formulas. Because of the nature of the formulas I'm
creating, it made sense to write my classes in .NET, and then register the
assembly via RegisterAssembly, and then instantiate the class via
CreateObject. This all works great.

The problem starts when I destroy the spreadsheet control. The add-in, and
all the resources it allocated, are never freed. So far, the only way I can
get the memory freed is by using a separate ApplicationDomain, which isn't a
practical solution in this case.

During my testing, I instantiate a form which contains the ActiveX
spreadsheet control, I invoke the AddIn method on that spreadsheet. Once
the form is closed, I set the form reference to null, then invoke
GC.Collect(). At this point, the amount of memory unreleased grows with the
amount of memory I consume via my test addin method, which simply creates
and populates a DataTable of a specified size with bogus data.

While searching for a solution to this problem, Alvin Bruney (MVP) suggested
that I try to us ReleaseComObject. It seems like a reasonable idea, but the
problem is, the object returned by CreateObject cannot be destroyed/released
via ReleaseComObject. The most puzzling thing about this is that the method
in the class instance is registered with the spreadsheet (it really works),
so it must have been converted to a COM class, but there's something special
going on, which I think you are alluding to here:
When two .NET objects communicate in the same process you don't go
through COM interop, so you don't have an RCW reference and therefore
IsCOMObject is false.

My guess is that the .NET managed object, which is instantiated as a COM
object and registered with the spreadsheet as an AddIn, cannot be GC'd
because the spreadsheet is somehow not releasing the Addin. Not knowing how
to proceed, I was hoping that invoking ReleaseComObject would work.

So, my new question is, is it possible to make a .NET class appear as a COM
class inside of .NET so that ReleaseComObject would actually work?
 
Corey,
Is it possible to make a .NET class appear as a COM class inside of .NET so
that ReleaseComObject would actually work?

The short answer is no, it's not possible.


Mattias
 
Back
Top