C
C#3y ago
Ainz

[Solved] COM Interop, Garbage Collection, and Runtime Callable Wrapper object management [Answered]

Essentially, this question is going to boil down to: when is it appropriate to call Marshal.FinalReleaseComObject() and should it be manually called or should the Garbage Collector handle it? (I'm fully expecting an $itdepends answer for this question.) Background: Apps at work interop with MS Excel and AutoCAD to drive these programs in-process and out-of-process. The .NET API around AutoCAD was written to function within the same process, not out-of-process. This forces any out of process .NET applications to utilize the ActiveX library to interop with AutoCAD. When application exits, the Excel and AutoCAD application processes are left open, visible to Task Manager., even though the application calls the .Quit(); method equivalents in each library. COM and RCWs: From my understanding, the runtime will create a Runtime Callable Wrapper overtop COM interfaces so that it is treated as a managed object. I'm working with public static fields within this code base, which makes them GC roots (?). If I'm understanding correctly, this means that the GC will not collect these instances until they are eligible for cleanup, effectively when nothing else is referencing them. Does this only happen when these variables are set to null? (See https://www.add-in-express.com/creating-addins-blog/2013/11/05/release-excel-com-objects/) Is this essentially the reason why, my COM objects are never dereferenced and released by the process? Excel Interop: The references to Excel.Worksheet, Excel.Workbook, and Excel.Application are marked as public static fields in the application code. When the application process exits, the application leaves the Excel process running in the background. If I call Marshal.FinalReleaseComObject on my Excel COM variables, the process will exit normally when running the application. What here actually "holds" the live Excel process captive from being released? The .NET application that launched Excel should have been cleaned up by the .NET Garbage collector and any unmanaged objects would be cleaned up by the Windows operating system, right? What exactly is the best practice? The Visual Studio team and some other users on sites like StackOverflow seem to state that manually releasing COM objects is something that shouldn't be done by the user and only handled by the garbage collector; but, others state that you must release COM objects when you are finished with them. Against: https://devblogs.microsoft.com/visualstudio/marshal-releasecomobject-considered-dangerous/#marshal-releasecomobject-a-problem-disguised-as-a-solution https://stackoverflow.com/a/25135685 For: https://www.add-in-express.com/creating-addins-blog/2013/11/05/release-excel-com-objects/ I've always read / have been told that COM Objects should always be manually released by the developer using Marshal.ReleaseComObject and Marshal.FinalReleaseComObject to ensure that the called application exits cleanly. And I feel like this is probably what should be done, but I'm wondering what side effects or gotchas I might end up encountering.
24 Replies
Ainz
AinzOP3y ago
thank you modix I hope this makes sense to whoever ends up reading this
230V
230V3y ago
@ LowLevel when
Xymanek
Xymanek3y ago
Ah yes
Ainz
AinzOP3y ago
It's that on a phone?
Xymanek
Xymanek3y ago
Yeah
Unknown User
Unknown User3y ago
Message Not Public
Sign In & Join Server To View
Ainz
AinzOP3y ago
I have thought about doing that, but I didn't want to crosspost anything, but I'm not really getting any answers either lol
Unknown User
Unknown User3y ago
Message Not Public
Sign In & Join Server To View
Sergio
Sergio3y ago
Nice formatting, Discord
Sergio
Sergio3y ago
What's the question?
Ainz
AinzOP3y ago
Xymanek has the same issue with formatting I've been working on some COM interop and doing some research on it and I've come across some conflicting information. Essentially, this question is going to boil down to: when is it appropriate to call Marshal.FinalReleaseComObject() and should it be manually called or should the Garbage Collector handle it? Some people you must release COM objects with ReleaseComObject and others are saying don't release anything because the garbage collector will handle it I've always been on the side of releasing it with Marshal.FinalReleaseComObject / ReleaseComObject
Sergio
Sergio3y ago
Mmmh not familiar with that API. The class and name kinda makes me think it probably should never be used tense also missing context here. How exactly are you doing COM interop? Using safe handles? Using COM interfaces? Using ComWrappers? Manually?
Ainz
AinzOP3y ago
COM Interfaces; the COM libraries that I'm working with are the Excel.Application, Workbook, Worksheet objects, and there's some AutoCAD COM Interfaces from their DLLs that are referenced in the project It's not safe handles and not ComWrappers. I think it's COM Interfaces that are exposed in the DLLs from the Excel COM libraries
Sergio
Sergio3y ago
In that case in pretty sure you're not supposed to do anything. The underlying type will have a finalizer and just do its thing
Ainz
AinzOP3y ago
If the host application, that calls the COM libraries to create a new Excel application, workbook, etc, and ends up exiting after everything is complete, then the garbage collector will run and clean up the resources as the process is exiting, right? Windows also keeps track of memory that's allocated during the process lifespan and should free that memory when the process exits too, correct?
Sergio
Sergio3y ago
No, the GC isn't guaranteed to run during process teardown Yes, if you terminate a process, all its memory goes away. Technically one could not free memory ever and as long as you have enough RAM, everything will work fine, then you can just close the process and poof, gone
Ainz
AinzOP3y ago
Ah, ok, interesting. What I was finding out through fixing one of our applications, is that the app would create an Excel.Application object and they didn't dispose of it or release the COM object. The object and the Excel process persisted even after the host application exited. Just remembering from working with COM a couple of years ago, that the recommendation at that time was to always release the COM object. So I added those lines of code and now the Excel application exits correctly. So I got curious and started researching again and ran into some different articles and conflicting information about how exactly COM objects should be handled, and now we are here lol If it's manual COM interop and / or the underlying type does not container a finalizer, then the allocated resources are not released?
Sergio
Sergio3y ago
Yeah, if you're doing manual COM interop you are responsible for properly tracking ref counts to every COM object
Ainz
AinzOP3y ago
Ah, sorry. Then I'm pretty sure it's all manual COM interop, as using Marshal.ReleaseComObject decrements the ref count in the runtime callable wrapper This is one of the articles that caused me to bring this up: https://stackoverflow.com/a/25135685. They're basically advocating for not using Marshal.ReleaseComObject and instead calling GC.Collect() & GC.WaitForPendingFinalizers() to release the resources
Unknown User
Unknown User3y ago
Message Not Public
Sign In & Join Server To View
Ainz
AinzOP3y ago
If I have to use COM interop, are using the other methods Sergio mentioned, like Safe Handles or COM Wrappers typically preferred?
Unknown User
Unknown User3y ago
Message Not Public
Sign In & Join Server To View
Accord
Accord3y ago
✅ This post has been marked as answered!
Want results from more Discord servers?
Add your server