在C#中正确处理COM互操作对象,特别是MS Office应用程序的释放。

14

我正在开发一个应用程序,它严重依赖于多个 Microsoft Office 产品,包括 Access、Excel、Word、PowerPoint 和 Outlook 等。在研究互操作性时,我发现从 VS2010 和 .NET 4 开始,我们可以庆幸地不再遭受PIAs的噩梦。

此外,我已经阅读了许多关于对象正确处理的文章,其中最明智的看起来是this

然而,该文章已经有五年之久了,在这个主题上没有太多权威出版物。以下是来自上述链接的代码示例:

' Cleanup:
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

Marshal.FinalReleaseComObject(worksheet)

oWB.Close(SaveChanges:=False)
Marshal.FinalReleaseComObject(workbook)

oApp.Quit()
Marshal.FinalReleaseComObject(application)

我想知道的是,按照今天的标准,这个问题有多准确,如果我希望支持我的应用程序在未来几年内,我应该注意什么?

更新:非常感谢提供一些可信的文章链接。顺便说一下,这不是一个服务器端应用程序。它将在计算机实验室中运行,我们让用户与我们为他们实例化的办公产品进行交互。

找到了:这篇三部分的文章可能是我能找到的最权威的解释。


为什么在应用程序运行时需要释放对象?当您的应用程序退出时,Office应用程序也将关闭。 - adrianm
1
是的,我知道在卸载应用程序域时会进行适当的垃圾回收。然而,我的情况既不是服务器端应用程序,也不是一次性客户端应用程序。它是一个混合体,在这种情况下,我需要确保任何打开的实例在容纳下一个用户之前已经被正确关闭。 - Raheel Khan
1
关于类似的话题:https://dev59.com/33VC5IYBdhLWcg3w4VNy#159419 - rkagerer
@rkagerer: 谢谢。这比我之前遇到的更全面的解释。另外,我不知道在事前和事后需要强制进行垃圾回收。 - Raheel Khan
不幸的是,“权威账户”文章已经有8年了,所以很难知道它描述的方法是否仍然适用于使用.Net 4执行Interop的方法。 - JoshL
3个回答

3

3
http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx - Hans Passant

2
根据您使用的 Office 版本以及服务器上发生的情况,是的,您可能需要进行一些复杂的操作来关闭某个 Office 应用程序的运行实例。例如,Word 在非交互式模式下打开时会出现不可预测(且不必要)的对话框(Office 应用程序都不太适合无人值守执行,因此建议即使使用最新版本也不要将其安装在服务器端)。
对于服务器端的情况,考虑使用 Aspose 或其他替代方案而不是 Office。对于交互式、本地使用的情况,由于 Office 自动化服务器是特别难以管理的非托管对象,因此有时可能需要进行“额外有力的终止”操作。

2

如果您想完全释放COM对象,特别是在MS Office COM对象中,强烈建议您释放必须使用的子对象,这些子对象位于父对象内部。

在您的示例中,我建议在释放单元格、范围或任何其他对象所属的工作表之前,先释放所有单元格、范围和其他可能使用的对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接