问题描述
当使用COM Interop with Office(通常是Excel)时,我总是小心确保我在每个引用上调用 Marshal.ReleaseComObject
,以避免Excel不退出的问题所述。
当我从OOB Silverlight应用程序(使用 AutomationFactory.CreateObject
)使用Interop时,如何确保Excel退出?
Silverlight没有 Marshal.ReleaseComObject
方法,甚至调用 GC.Collect
和
当然,Microsoft没有将此功能添加到Silverlight,而没有释放COM引用的机制。对我来说,这似乎是一个showstopper自动化进程外COM服务器,如Excel。
令人惊讶的ommission,更是如此的Pete布朗在5.5节他的书Silverlight 4 in Action中对 AutomationFactory.CreateObject
的说法是:
更新以回应汉斯的评论。
我不相信沉默刺客问题存在于Office应用程序的典型自动化中。一个常见的用法可能看起来像下面,我已经看到在WinForms应用程序中反复使用,没有遇到过由Hans链接的文章中描述的中毒的RCW:
- 创建Excel.Application实例
- 打开或创建工作簿
- 将数据写入工作簿
- 显示Excel,如果一切顺利,关闭工作簿,如果没有,调用Application.Quit。
- 调用Marshal.ReleaseComObject释放所有Excel对象引用。 li>
如果Hans不推荐调用Marshal.ReleaseComObject,将会保留Excel.exe运行的多个副本,非常不受欢迎。
UPDATE 2
这是从Pete Brown的书Silverlight 4的源代码中的一个示例,在这个页面上有一个下载链接。样品溶液AutomatingExcel在Ch05.zip / 5.03中。要重现:
- 确保没有运行Excel实例
- 运行AutomatingExcel示例
- 打开Excel工作簿
- 关闭Excel
- 使用任务管理器观察Excel仍在运行。
将所有动态变量设置为null并调用GC.Collect()似乎像AnthonyWJones的答案中所指出的那样工作。
UPDATE 2
Otaku的答案就是我要找的 - 在using语句中引用COM引用被释放,而不需要调用GC.Collect。有些实验表明,与上面引用的知识库文章中描述的标准 Marshal.ReleaseComObject
解决方案不同,它更能容忍无法处理每个引用。
$ b
这是非常有趣的,有一个权威取得必须处理,以确保所有的Excel参考。解决方案
您可以实现 IDisposable
界面。我看到的最好的例子是。博客条目是日语,但是在Chrome中打开,如果您不阅读日语,则允许Google为您翻译页面。
此外,如果您只想要源代码示例的COM包装器直接可以下载它的示例应用程序:。
When using COM Interop with Office (usually Excel), I always carefully ensure I call Marshal.ReleaseComObject
on every reference, to avoid the problem where Excel doesn't quit as described in this KB article.
How can I ensure Excel quits when I use Interop from an OOB Silverlight application (with AutomationFactory.CreateObject
)?
Silverlight doesn't have a Marshal.ReleaseComObject
method and even calling GC.Collect
and GC.WaitForPendingFinalizers
doesn't help.
Surely Microsoft hasn't added this feature to Silverlight without a mechanism to release COM references? This seems to me to be a showstopper for automating out-of-process COM servers such as Excel.
A surprising ommission, all the more so as Pete Brown in section 5.5 of his book "Silverlight 4 in Action" goes as far as to say about AutomationFactory.CreateObject
, that:
UPDATE in response to Hans' comments.
I'm not convinced the "silent assassin" problem exists in typical automation of Office apps. A common use might look something like the following, which I've seen used repeatedly in WinForms applications without ever coming across the "poisoned RCW" described in the article linked by Hans:
- Create an Excel.Application instance
- Open or create a workbook
- Write data to the workbook
- Show Excel if all went well, close the workbook and call Application.Quit if not.
- Call Marshal.ReleaseComObject to release all Excel object references.
Failing to call Marshal.ReleaseComObject as recommended by Hans will leave multiple copies of Excel.exe running, as described in the KB article mentioned above - highly undesirable.
UPDATE 2
The sample I'm using to repro this is a sample from the source code for Pete Brown's book Silverlight 4 in action, there's a download link on this page. The sample solution AutomatingExcel is in Ch05.zip / 5.03. To repro:
- Make sure no instances of Excel are running
- Run AutomatingExcel sample
- An Excel workbook is opened
- Close Excel
- Observe with Task Manager that Excel is still running.
Setting all the dynamic variables to null and calling GC.Collect() seems to work as pointed out in AnthonyWJones's answer.
UPDATE 2
Otaku's answer is what I was looking for - by wrapping references in a using statement the COM references are released without the need to call GC.Collect. A bit of experimentation shows that it's more tolerant of failing to dispose every single reference, unlike the standard Marshal.ReleaseComObject
solution described in the KB article referenced above.
It would be interesting to have an authoritative take on exactly what must be disposed to ensure that all Excel references are released.
You could implement the IDisposable
interface. The best example of this I've seen is at http://csfun.blog49.fc2.com/blog-entry-79.html. The blog entry is in Japanese, but open in Chrome and let Google do the page translation for you if you don't read Japanese.
Also, if you just want the source code example of the COM wrapper directly you can download the sample app it comes in: SilverOffice.
这篇关于如何在Silverlight 4中释放COM对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!