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

时间:2012-11-01 14:45:46

标签: c# .net-3.5 marshalling com-interop excel-interop

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

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

如果您无法从标题中分辨出来,我已经完成了我的研究。标题暗示了这篇文章:
How do I properly clean up Excel interop objects?

2008年首先提出的建议是,当时的建议非常有用且非常可靠(尤其是“绝不使用带有com对象的2个点”),但现在看来已经过时了。 2010年3月,Visual Studio团队发布了一篇博客文章,警告其他程序员Marshal.ReleaseComObject [is] Considered Dangerous。这篇文章提到了两篇文章,cbrumme's WebLog > ReleaseComObjectThe mapping between interface pointers and runtime callable wrappers (RCWs),表明人们一直错误地使用ReleaseComInterop(cbrumme:“如果你是一个使用适量的COM对象的客户端应用程序在托管代码中自由使用,不应使用ReleaseComObject“)。

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

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


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

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

这是我的实施:

class AutoCleanup<T> : 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<T> WithComCleanup<T>( this T target ) {
        return new AutoCleanup<T>( target );
    }

}

1 个答案:

答案 0 :(得分:1)

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

请查看此文档代码段: http://netoffice.codeplex.com/wikipage?title=Tec_Documentation_English_Management

您可以在教程文件夹

中找到一些用于com代理管理的showstopper项目