截至今天,使用COM对象的正确方法是什么? 您所在的位置:网站首页 对象range的方法global失败 截至今天,使用COM对象的正确方法是什么?

截至今天,使用COM对象的正确方法是什么?

2023-03-13 22:22| 来源: 网络整理| 查看: 265

using System; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; namespace TestCsCom { class Program { static void Main(string[] args) { // NOTE: Don't call Excel objects in here... // Debugger would keep alive until end, preventing GC cleanup // Call a separate function that talks to Excel DoTheWork(); // Now let the GC clean up (repeat, until no more) do { GC.Collect(); GC.WaitForPendingFinalizers(); } while (Marshal.AreComObjectsAvailableForCleanup()); } static void DoTheWork() { Application app = new Application(); Workbook book = app.Workbooks.Add(); Worksheet worksheet = book.Worksheets["Sheet1"]; app.Visible = true; for (int i = 1; i

您将看到Excel进程正确关闭,表明所有COM对象都已正确清理.

VSTO不会改变任何这些问题 - 它只是一个包装和扩展本机Office COM对象模型的.NET库.

关于这个问题存在很多虚假信息和混淆,包括MSDN和StackOverflow上的许多帖子.

什么最终说服我仔细看看并找出正确的建议是这篇文章https://blogs.msdn.microsoft.com/visualstudio/2010/03/01/marshal-releasecomobject-considered-dangerous/与找到在StackOverflow答案的调试器下保持活动引用的问题.

此一般指导的一个例外是COM对象模型要求以特定顺序释放接口.此处描述的GC方法无法控制GC释放COM对象的顺序.

我没有提及是否会违反COM合同.通常,我希望COM层次结构使用内部引用来确保正确管理对序列的任何依赖性.例如,在Excel的情况下,可以期望Range对象保持对父Worksheet对象的内部引用,以便对象模型的用户不需要显式保持两者都存活.

在某些情况下,即使Office应用程序对释放COM对象的顺序也很敏感.一个案例似乎是使用OLE嵌入时 - 请参阅https://blogs.msdn.microsoft.com/vsofficedeveloper/2008/04/11/excel-ole-embedding-errors-if-you-have-managed-add -in-下沉应用事件合的Excel-2 /

因此,如果对象以错误的顺序发布,则可能会创建一个COM对象模型失败,并且与这种COM模型的互操作将需要更多的关注,并且可能需要手动干涉引用.

但是对于与Office COM对象模型的一般互操作,我同意VS博客文章称为"Marshal.ReleaseComObject - 一个伪装成解决方案的问题".

1> Govert..:

.NET/COM互操作设计精良,工作正常.特别是,.NET垃圾收集器正确跟踪COM引用,并且当它们没有剩余的运行时引用时将正确释放COM对象.通过调用干扰COM对象的引用计数,Marshal.ReleaseComObject(...)或者Marshal.FinalReleaseComObject(...)是一种危险但常见的反模式.不幸的是,一些不好的建议来自微软.

您的.NET代码可以正确地与COM交互,同时忽略所有5个规则.如果确实需要触发不再从运行时引用的COM对象的确定性清理,则可以安全地强制GC(并可能等待终结器完成).否则,您不必在代码中执行任何特殊操作来处理COM对象.

有一个重要的警告,可能有助于混淆垃圾收集器的作用.在调试.NET代码时,局部变量人为地将其生命周期延长到方法的末尾,以支持在调试器下观察变量.这意味着您可能仍然具有对COM对象的托管引用(因此GC不会清理),而不仅仅是期望表单只是查看代码.此问题的一个很好的解决方法(仅在调试器下发生)是从GC清理调用中拆分COM调用的范围.

例如,这里有一些与Excel交互的C#代码,并且可以正常清理.您可以粘贴到控制台应用程序中(只需添加对Microsoft.Office.Interop.Excel的引用):

using System; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; namespace TestCsCom { class Program { static void Main(string[] args) { // NOTE: Don't call Excel objects in here... // Debugger would keep alive until end, preventing GC cleanup // Call a separate function that talks to Excel DoTheWork(); // Now let the GC clean up (repeat, until no more) do { GC.Collect(); GC.WaitForPendingFinalizers(); } while (Marshal.AreComObjectsAvailableForCleanup()); } static void DoTheWork() { Application app = new Application(); Workbook book = app.Workbooks.Add(); Worksheet worksheet = book.Worksheets["Sheet1"]; app.Visible = true; for (int i = 1; i

您将看到Excel进程正确关闭,表明所有COM对象都已正确清理.

VSTO不会改变任何这些问题 - 它只是一个包装和扩展本机Office COM对象模型的.NET库.

关于这个问题存在很多虚假信息和混淆,包括MSDN和StackOverflow上的许多帖子.

什么最终说服我仔细看看并找出正确的建议是这篇文章https://blogs.msdn.microsoft.com/visualstudio/2010/03/01/marshal-releasecomobject-considered-dangerous/与找到在StackOverflow答案的调试器下保持活动引用的问题.

此一般指导的一个例外是COM对象模型要求以特定顺序释放接口.此处描述的GC方法无法控制GC释放COM对象的顺序.

我没有提及是否会违反COM合同.通常,我希望COM层次结构使用内部引用来确保正确管理对序列的任何依赖性.例如,在Excel的情况下,可以期望Range对象保持对父Worksheet对象的内部引用,以便对象模型的用户不需要显式保持两者都存活.

在某些情况下,即使Office应用程序对释放COM对象的顺序也很敏感.一个案例似乎是使用OLE嵌入时 - 请参阅https://blogs.msdn.microsoft.com/vsofficedeveloper/2008/04/11/excel-ole-embedding-errors-if-you-have-managed-add -in-下沉应用事件合的Excel-2 /

因此,如果对象以错误的顺序发布,则可能会创建一个COM对象模型失败,并且与这种COM模型的互操作将需要更多的关注,并且可能需要手动干涉引用.

但是对于与Office COM对象模型的一般互操作,我同意VS博客文章称为"Marshal.ReleaseComObject - 一个伪装成解决方案的问题".

我想补充一点,有许多COM对象用非托管代码编写,确实有bug(不是谈论微软的大的一般都可以).这些错误导致P/Invoke被打破的错误印象,因为它们有时迫使.NET开发人员应用COM恐慌巫术魔法(在任何地方添加ReleaseComObject,以相反的顺序释放对象等)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有