Click here to Skip to main content
Click here to Skip to main content

Tagged as

Proper Way of Releasing COM Objects in .NET

, 16 Mar 2011
Rate this:
Please Sign up or sign in to vote.
Fully release resouces engaged by COM objects
This is an old version of the currently published tip/trick.
Recently, I am working with a project which inter-operates COM interfaces provided by the Microsoft Office Document Imaging (MODI) component. (Yes, I know that it is deprecating, however, nothing can substitute it at this moment.)
 
Several articles on CodeProject have discussed about that component (a good one of them is this, OCR with Microsoft® Office[^]), yet gaps are left between simple introductions and practical use.
 
To make MODI work, we have to accept that MODI only processes TIFF images, thus the image has to be converted to a temporary TIFF file and processed by the On Screen Recognition (OCR) engine of MODI. Afterwards, the temporary TIFF file should be removed from the hard drive.
 
The problem in the cleanup process can cost you some time. And that is what this article is talking about. The following code demonstrates the situation about the problem, which is very common around programmers who work with MODI or other COM objects for the first time.
 
MODI.Document doc = new MODI.Document(); // Create the COM instance
doc.Create("temp.tif");
doc.OCR(MODI.MiLANGUAGES.miLANG_SYSDEFAULT, true, true);
MODI.Image image = (MODI.Image)doc.Images[0]; // get the first MODI.Image object from Modi.Document's Images collection
MODI.Layout layout = image.Layout; // get the Layout property of the Modi.Image object

// ...
// do something with the objects gained from MODI
doc.Close(false); 
Marshal.FinalReleaseComObject (doc);
doc = null; 
GC.Collect();
File.Delete ("temp.tif"); // here an exception of file-in-use will be thrown
 
The above code instantiates a COM object doc, works with the COM object's properties and finally tries to release the instantiated COM object by using Marshal.FinalReleaseComObject to release the MODI instance (doc), setting the MODI instance to null and even calling GC.Collect, hoping the resource consumed by it can be fully released.
 
However, an exception will still surely show up, from the last line of code, telling you "temp.tif" is in used by "another process" and cannot be deleted. Obviously, no other process is working with that darned file.
 
The problem is that the two objects (image and layout) of type MODI.Image and MODI.Layout, which appear to be properties of the doc object though, are actually COM objects as well. Simply releasing the instantiated COM object doc is not enough. We still have to release other COM objects obtained from its property accessors. So, the answer to solve the file engagement issue is to release those two objects gained from property access of the COM object doc, like the following code shows.
doc.Close(false);
Marshal.FinalReleaseComObject (doc);
// Release objects obtained from the MODI.Document instance
Marshal.FinalReleaseComObject (image);
Marshal.FinalReleaseComObject (layout);
doc = null;
// Calling GC.Collect is not necessary here
// GC.Collect();
File.Delete ("temp.tif");
 
After that, the file handle to "temp.tif" assigned by MODI will be released and the File.Delete method will run happily without complaining that the file is occupied.
 
In production code, the COM object releasing code may be placed in the finally section of a try...catch...finally block to ensure that the resource is fully released.
 
A side note:
If you are used to chained property access in .NET, such as obj.PropertyA.PropertyB. You'd better avoid doing so when you are inter-operating with COM. That's because the intermediate object obj.PropertyA is "hidden" as an anonymous reference to a COM object and it might not get a chance to be released. The workaround is explicitly declaring a variable to hold the reference to the intermediate object and using Mashal.FinalReleaseComObject onto that reference when the object is no longer used.
 
P.S. I am also new to COM inter-operation in .NET. Please correct me if anything above is wrong.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

wmjordan

China China
Chinese Poetry Lover.
Programmer.

Comments and Discussions


Discussions posted for the Published version of this article. Posting a message here will take you to the publicly available article in order to continue your conversation in public.
 
QuestionGood Article, but Didnt work out well PinmemberHifni Shahzard1-Jul-12 18:58 
AnswerRe: Good Article, but Didnt work out well PinmemberHifni Shahzard10-Jul-12 18:58 
GeneralReason for my vote of 2 Alternative 1 is the proper way to d... PinmemberMichael B. Hansen13-Feb-12 1:53 
GeneralReason for my vote of 2 The article name is misleading. You ... Pinmemberveki-peki15-Mar-11 23:01 
GeneralRe: Thank you for the 2. The reason I post this is because of th... Pinmemberwmjordan16-Mar-11 0:05 
GeneralExactly what I do PinmemberStevenS_Dev1-Mar-11 7:49 
GeneralRe: Exactly what I do Pinmemberwmjordan16-Mar-11 0:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 16 Mar 2011
Article Copyright 2011 by wmjordan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid