如何在C#,2012版中正确清理Excel互操作对象

我正在用C#编写一个应用程序,它将通过互操作打开一个Excel电子表格(2007年,现在),做一些魔术,然后关闭。 “魔术”部分非常重要,因此该应用程序将包含对Excel生成的许多COM对象的许多引用。

我以前写过这种应用程序(事实上已经太多次了)但是我从来没有找到一种舒适的,“好闻”的方法来与COM对象进行交互。 问题部分在于,尽管进行了大量研究,我仍然不能完全理解COM,部分是因为互操作包装器隐藏了很多可能不应该隐藏的内容。 事实上,来自社区的这么多不同的,相互冲突的建议只会让事情变得更糟。

如果您无法从标题中分辨出来,我已经完成了我的研究。 标题暗示了这篇文章:
如何正确清理Excel互操作对象?

在2008年首次询问时,这个建议在当时非常有用且非常可靠(特别是“从不使用带有com对象的2个点”位),但现在看来已经过时了。 2010年3月,Visual Studio团队发布了一篇博客文章,警告其他程序员Marshal.ReleaseComObject [is] Considered Dangerous 。 文章提到了两篇文章, cbrumme的WebLog> ReleaseComObject以及接口指针和运行时可调用包装器(RCW)之间的映射 ,表明人们一直错误地使用ReleaseComInterop(cbrumme:“如果你是一个使用适度数量的客户端应用程序在托管代码中自由传递的COM对象,不应使用ReleaseComObject“)。

有没有人有一个中等复杂的应用程序的例子,最好使用多个线程,能够成功地在内存泄漏之间导航(Excel在应用程序关闭后继续在后台运行)和InvalidComObjectExceptions? 我正在寻找能够在创建它的上下文之外使用COM对象的东西,但是一旦应用程序完成它仍然可以清理它:内存管理策略的混合,可以有效地跨越托管/非管理鸿沟。

对于讨论这个问题的正确方法的文章或教程的引用将是一个非常受欢迎的替代方案。 我最好的Google-fu努力已经返回了显然不正确的ReleaseComInterop方法。


更新:
(这不是答案)
发布后不久我发现了这篇文章:
Jake Ginnivan的VSTO和COM Interop

我已经能够通过扩展方法实现他在“AutoCleanup”类中包装COM对象的策略,我对结果非常满意。 虽然它没有提供允许COM对象跨越创建它们的上下文边界的解决方案,并且仍然使用ReleaseComObject函数 ,但它至少提供了一个简洁易读的解决方案。

这是我的实现:

class AutoCleanup : IDisposable { public T Resource { get; private set; } public AutoCleanup( T resource ) { this.Resource = resource; } ~AutoCleanup() { this.Dispose(); } private bool _disposed = false; public void Dispose() { if ( !_disposed ) { _disposed = true; if ( this.Resource != null && Marshal.IsComObject( this.Resource ) ) { Marshal.FinalReleaseComObject( this.Resource ); } else if ( this.Resource is IDisposable ) { ( (IDisposable) this.Resource ).Dispose(); } this.Resource = null; } } } static class ExtensionMethods { public static AutoCleanup WithComCleanup( this T target ) { return new AutoCleanup( target ); } } 

你现在有用于COM代理管理的NetOffice概念吗? NetOffice使用com代理的包装类和IDisposable模式。 NetOffice保留代理的父 – 子关系。 处理工作表,并且还处理了来自实例(单元格,样式)等的所有已创建的子项。 您还可以使用特殊事件或静态属性来观察应用程序中的开放代理的数量。

只需看一下这个文档片段: http : //netoffice.codeplex.com/wikipage?title = Tec_Documentation_English_Management

你会在tutorials文件夹中找到一些用于com代理管理的showstopper项目