All of these questions:
- Excel 2007 Hangs When Closing via .NET
- How to properly clean up Excel interop objects in C#
- How to properly clean up interop objects in C#
struggle with the problem that C# does not release the Excel COM objects properly after using them. There are mainly two directions of working around this issue:
- Kill the Excel process when Excel is not used anymore.
- Take care to explicitly assign each COM object used to a variable first and to guarantee that eventually, Marshal.ReleaseComObject is executed on each.
Some have stated that 2 is too tedious and there is always some uncertainty whether you forget to stick to this rule at some places in the code. Still 1 seems dirty and error-prone to me, also I guess that in a restricted environment trying to kill a process could raise a security error.
So I've been thinking about solving 2 by creating another proxy object model which mimics the Excel object model (for me, it would suffice to implement the objects I actually need). The principle would look as follows:
- Each Excel Interop class has its proxy which wraps an object of that class.
- The proxy releases the COM object in its finalizer.
- The proxy mimics the interface of the Interop class.
- Any methods that originally returned a COM object are changed to return a proxy instead. The other methods simply delegate the implementation to the inner COM object.
Example:
public class Application
{
private Microsoft.Office.Interop.Excel.Application innerApplication
= new Microsoft.Office.Interop.Excel.Application innerApplication();
~Application()
{
Marshal.ReleaseCOMObject(innerApplication);
innerApplication = null;
}
public Workbooks Workbooks
{
get { return new Workbooks(innerApplication.Workbooks); }
}
}
public class Workbooks
{
private Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks;
Workbooks(Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks)
{
this.innerWorkbooks = innerWorkbooks;
}
~Workbooks()
{
Marshal.ReleaseCOMObject(innerWorkbooks);
innerWorkbooks = null;
}
}
My questions to you are in particular:
- Who finds this a bad idea and why?
- Who finds this a gread idea? If so, why hasn't anybody implemented/published such a model yet? Is it only due to the effort, or am I missing a killing problem with that idea?
- Is it impossible/bad/error-prone to do the ReleaseCOMObject in the finalizer? (I've only seen proposals to put it in a Dispose() rather than in a finalizer - why?)
- If the approach makes sense, any suggestions to improve it?