If COM Interop objects are not properly released in your .NET code, the program that your .NET program is communicating with via COM Interop will remain in the Windows operating system task list without a visible window. You can see it in the Details tab of Task Manager.
The common language runtime exposes COM objects through a proxy called the Runtime Callable Wrapper (RCW). To a .NET application, a RCW looks like an ordinary .NET object. It handles calls between a .NET client and a COM object (e.g. The EXCEL.EXE application and objects within EXCEL.EXE) marshaling arguments and return values between the .NET client and the COM object; converting them when necessary.
For each COM object, the .NET runtime creates a single RCW regardless of the number of references to that object. A reference count is incremented each time a new reference is made to the RCW of an instantiated COM object. Calling a "
Quit" or "
Exit" method followed by a "
Dispose" method on a COM object will not free up all of the references. The example code in this tip will ensure that all references are released so that the called COM program will end properly.
Coding Model for COM Interop
- Instantiate COM objects just before they are needed.
FinalReleaseComObject(obj) to release objects as soon as they are not needed.
FinalReleaseComObject on the most recently created objects first.
- Use the .NET Garbage Collection methods to force garbage collection.
COM Interop Example
My original example is VB .NET code. I used the developerFusion Convert VB .NET to C# tool to convert my VB .NET code to the C# code included in this tip.
Dim oApp As Excel.Application
oApp = DirectCast(CreateObject("Excel.Application"), Excel.Application)
oApp.Visible = True
oApp = Nothing GC.Collect() GC.WaitForPendingFinalizers()
Excel.Application oApp = default(Excel.Application);
oApp = (Excel.Application)Interaction.CreateObject("Excel.Application");
oApp.Visible = true;
oApp = null; GC.Collect(); GC.WaitForPendingFinalizers();
Points of Interest
Below are links to several articles about COM Interop. Thanks to those authors for their fine articles.
- 29 March 2013 - Initial version
- 23 October 2013 - Minor edit
- 12 November 2013 - Removed While Loop of ReleaseComObject and replaced with FinalReleaseComObject
I’m retired. When I started my career, programming projects consisted of plugging wires into plug boards to create punch card processing applications to be run on electrical accounting machine like the IBM 402, 407, 085, 088, 514, 519, etc. From there, I moved to writing SPS and Autocoder applications on an IBM 1401 with 4K of memory eventually upgraded to 16K of memory. After many years of migrating my skills to various languages on various hardware platforms, I became an Information Technology Director where I didn’t need to program anymore. So, starting in 1996, I volunteered my time with a local community cable television organization and built some applications to help them run their operations. Originally in Clipper Summer 1987 and later Clipper 5.2, I migrated and enhanced those applications to VB .NET 2003 in 2003. I retired from my full-time job in 2010. Since then, I have continued to support the local community cable tv organization's applications. In 2013, I migrated the VB .NET 2003 Solution to VB .NET 2012 so that it can run on 64-bit computers and interact with Microsoft Office 2010. The upgrade went smoothly. In mid 2013, I developed a VB .NET 2012 application for them to download election results data from the Secretary of State's web site, format the results and send them to a VizRT character generator for on-air display.