微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我正在用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 );
    }

}

解决方法

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐