.NET COM Object Injection

I have an ASP.NET 2.0 application in IIS that has the function of exporting some data to a software called HFM (Oracle Hyperion Financial Management). To perform this export, the .net application uses an API based on COM objects provided by the HFM client (the client is installed on the same machine as the server, etc.).

My problem is that the API provides a method to connect to the HFM server, but not to disconnect.
The documentation says that to shutdown the application, the application must call the Marshal.ReleaseComObject () method for each COM object it creates . But there are a lot of complicated things going on and I cannot free the entire created object.
Therefore my application is not shutting down.

I noticed that when I replace the DLLs of the ASP.NET application (which seems to restore the .NET generated objects), the application shuts down automatically.

I tried several times to call:

GC.Collect();
GC.WaitForPendingFinalizers();

      

But the problem remains. I'm looking for a way to make sure ANY object is created, even COM objects are released. I've tried with Marshal.FinalReleaseComObject () but it is no better.

When I put lock () in this section, there is always at most one user in that part, so I can even use hardcore methods to release COM objects.

Is there a way to find out which object, or at least the type of object that hasn't been released?

Thank you for your help.

+1


source to share


3 answers


But there are a lot of complicated things going on and I cannot free the entire created object.

There is your problem.



You are looking for an easy way out. But you are working with COM. The only easy way out is when your process / appdomain is down.

+1


source


Can you put a generic wrapper type that implements IDisposable around each of these COM instances?

You can then call Marshal.FinalReleaseComObject (or turn the cycle Marshal.ReleaseComObject checks refcount) in the method Dispose only to instantiate the COM-object with the operator using that refers to your type of wrapper.



Another benefit of this wrapper trick is that you can use the CLR profiler to check which instances of your type have not yet been in this way, answering your last question.

+2


source


It is absolutely essential that you set the variable to Null / Nothing after calling Marshal.ReleaseComObject or Marshal.FinalReleaseComObject.

Dim cn As ADODB.Connection
cn = New ADODB.Connection
cn.Open(_cnnstr)
cn.Execute(sbDML.ToString)
cn.Close()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cn)
cn = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!

      

Also, I've noticed that creating another method helps avoid problems with local COM objects (variables placed on the stack). For example, if you have one method that does everything, wrap it in a different way, add a call to garbage collection, then call the wrapper.

Public Sub MainMethod
    '...
    Marshal.FinalReleaseComObject(foo)
    foo = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!
End Sub

Public Sub WrapperMethod
    Call MainMethod
    GC.Collect()
End Sub

      

I believe that the extra call to create an add-on stack for local variables makes the objects completely collect faster and frees up the COM objects completely.

I have followed this pattern for a couple of years now and have not had any problems since then.

+1


source







All Articles