在代码中正确释放 COM 对象
Proper release of COM objects in code
我刚刚开始将一些代码从 VBA 迁移到 VB.Net。所以我绝对是 VB.Net 的初学者——但我想把事情做好。也许我的一些问题很愚蠢,但我想那是因为我是初学者。
作为第一个练习,我开发了我的第一段代码(见下文)。现在我想我必须再次释放所有 COM 对象。其中两个在编写代码时已经抛出错误。而其他人则在运行时抛出错误。
但有趣的是:天气我是否释放其余的 COM 对象(通过将 Marshal.Release 的相关未注释行也添加到注释中——然后所有以 [=82 开头的行=] 是注释行)代码的行为在我看来是完全一样的。
谁能告诉我哪里可以see/find区别?
网上说肯定有区别?
但我想我只是不明白(直到现在)。
除此之外,我还有很多问题:
- 是否每个“Dim”语句都会创建一个 COM 对象 - 必须稍后发布?
- 如果没有,如何检测是否已创建 COM 对象?哪些“Dim”语句创建 COM 对象,哪些不创建?
- 在这个例子中:
Dim ActiveWindow As Object = Nothing Try ActiveWindow = Me.HostApplication.ActiveWindow() Catch End Try
是
Marshal.ReleaseComObject(ActiveWindow)
相同
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
?
- 据此:
http://www.codeproject.com/Tips/235230/Proper-Way-of-Releasing-COM-Objects-in-NET
每个"level"像这样分开释放不是更好吗:
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
Marshal.ReleaseComObject(Me.HostApplication)
Marshal.ReleaseComObject(Me)
总体:我是不是想释放太多?还是正确/好的做法?
"GC.Collect()" 和“... = Null”与这一切有什么关系?我根本没用过。我应该更好地使用它吗?为什么? ( "... = Null" 我在这里看到过:
http://www.codeproject.com/Tips/162691/Proper-Way-of-Releasing-COM-Objects-in-NET)
为什么我会收到“ShapeCount was not declared …”- 如果我尝试执行“Marshal.ReleaseComObject(ShapeCount)
”会出错?与“ShRange”相同。我认为这些也是 COM 对象?!?
我如何注意到何时是再次释放 COM 对象的最佳时机?当我 process/debug 使用 F11 逐步编写我的代码时,我可以确定最佳(最快)的发布点吗?到目前为止,我对何时不再需要 COM 对象并可以释放它没有“感觉”。
非常欢迎任何帮助和解释。
这是我正在谈论的代码:
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.Windows.Forms
Imports AddinExpress.MSO
Imports PowerPoint = Microsoft.Office.Interop.PowerPoint
'Add-in Express Add-in Module
<GuidAttribute("D75C609E-7632-400F-8A6F-6A6E6E744E75"),
ProgIdAttribute("MyAddin8.AddinModule")> _
Public Class AddinModule
Inherits AddinExpress.MSO.ADXAddinModule
#Region " Add-in Express automatic code "
[…]
#End Region
Public Shared Shadows ReadOnly Property CurrentInstance() As AddinModule
Get
Return CType(AddinExpress.MSO.ADXAddinModule.CurrentInstance, AddinModule)
End Get
End Property
Public ReadOnly Property PowerPointApp() As PowerPoint._Application
Get
Return CType(HostApplication, PowerPoint._Application)
End Get
End Property
Private Sub AdxRibbonButton2_OnClick(sender As Object, control As IRibbonControl, pressed As Boolean) Handles AdxRibbonButton2.OnClick
MsgBox(GetInfoString2())
End Sub
Friend Function GetInfoString2() As String
Dim ActiveWindow As Object = Nothing
Try
ActiveWindow = Me.HostApplication.ActiveWindow()
Catch
End Try
Dim Result As String = "No document window found!"
If Not ActiveWindow Is Nothing Then
Select Case Me.HostType
Case ADXOfficeHostApp.ohaPowerPoint
Dim Selection As PowerPoint.Selection =
CType(ActiveWindow, PowerPoint.DocumentWindow).Selection
Dim WindowViewType As PowerPoint.PpViewType = PowerPoint.PpViewType.ppViewNormal
Dim SlideRange As PowerPoint.SlideRange = Selection.SlideRange
Dim SlideCountString = SlideRange.Count.ToString()
If WindowViewType = 9 And SlideCountString < 2 Then
Dim ShRange As PowerPoint.ShapeRange = Nothing
Try
ShRange = Selection.ShapeRange
Catch
End Try
If Not ShRange Is Nothing Then
Dim ShapeCount = ShRange.Count.ToString()
Result = "You have " + ShapeCount _
+ " shapes selected."
Else
Result = "You have 0 shapes selected."
End If
End If
'Marshal.ReleaseComObject(ShapeCount)
'Marshal.ReleaseComObject(ShRange)
'Marshal.ReleaseComObject(WindowViewType)
'Marshal.ReleaseComObject(SlideCountString)
Marshal.ReleaseComObject(SlideRange)
Marshal.ReleaseComObject(Selection)
Case Else
Result = AddinName + " doesn't support " + HostName
End Select
'Marshal.ReleaseComObject(Me.HostType)
'Marshal.ReleaseComObject(Result)
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
Marshal.ReleaseComObject(Me.HostApplication)
'Marshal.ReleaseComObject(Me)
End If
Return Result
End Function
End Class
FinalReleaseComObject
调用 ReleaseComObject
直到 returns 0,这意味着释放 COM 对象。以相反的顺序调用它们,如 Excel objects(Application, Workbook, Worksheet) 是处理相关 COM 对象的正确方法。
Exception Condition
ArgumentException
o is not a valid COM object.
ArgumentNullException
o is null.
Marshal class 的 ReleaseComObject 方法减少与指定 COM 对象关联的指定运行时可调用包装器 (RCW) 的引用计数,它不会释放对象。它来自 COM 性质。
通常您需要释放从 Office(在您的例子中是 PowerPoint)对象模型返回的每个对象。异常是作为参数传递给事件处理程序的对象。
您可以阅读更多相关内容并在 When to release COM objects in Office add-ins developed in .NET 文章中找到您的多个问题的答案。
我刚刚开始将一些代码从 VBA 迁移到 VB.Net。所以我绝对是 VB.Net 的初学者——但我想把事情做好。也许我的一些问题很愚蠢,但我想那是因为我是初学者。
作为第一个练习,我开发了我的第一段代码(见下文)。现在我想我必须再次释放所有 COM 对象。其中两个在编写代码时已经抛出错误。而其他人则在运行时抛出错误。
但有趣的是:天气我是否释放其余的 COM 对象(通过将 Marshal.Release 的相关未注释行也添加到注释中——然后所有以 [=82 开头的行=] 是注释行)代码的行为在我看来是完全一样的。
谁能告诉我哪里可以see/find区别?
网上说肯定有区别? 但我想我只是不明白(直到现在)。
除此之外,我还有很多问题:
- 是否每个“Dim”语句都会创建一个 COM 对象 - 必须稍后发布?
- 如果没有,如何检测是否已创建 COM 对象?哪些“Dim”语句创建 COM 对象,哪些不创建?
- 在这个例子中:
Dim ActiveWindow As Object = Nothing Try ActiveWindow = Me.HostApplication.ActiveWindow() Catch End Try
是
Marshal.ReleaseComObject(ActiveWindow)
相同
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
?
- 据此:
http://www.codeproject.com/Tips/235230/Proper-Way-of-Releasing-COM-Objects-in-NET
每个"level"像这样分开释放不是更好吗:
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
Marshal.ReleaseComObject(Me.HostApplication)
Marshal.ReleaseComObject(Me)
总体:我是不是想释放太多?还是正确/好的做法?
"GC.Collect()" 和“... = Null”与这一切有什么关系?我根本没用过。我应该更好地使用它吗?为什么? ( "... = Null" 我在这里看到过:
http://www.codeproject.com/Tips/162691/Proper-Way-of-Releasing-COM-Objects-in-NET)
为什么我会收到“ShapeCount was not declared …”- 如果我尝试执行“
Marshal.ReleaseComObject(ShapeCount)
”会出错?与“ShRange”相同。我认为这些也是 COM 对象?!?我如何注意到何时是再次释放 COM 对象的最佳时机?当我 process/debug 使用 F11 逐步编写我的代码时,我可以确定最佳(最快)的发布点吗?到目前为止,我对何时不再需要 COM 对象并可以释放它没有“感觉”。
非常欢迎任何帮助和解释。
这是我正在谈论的代码:
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.Windows.Forms
Imports AddinExpress.MSO
Imports PowerPoint = Microsoft.Office.Interop.PowerPoint
'Add-in Express Add-in Module
<GuidAttribute("D75C609E-7632-400F-8A6F-6A6E6E744E75"),
ProgIdAttribute("MyAddin8.AddinModule")> _
Public Class AddinModule
Inherits AddinExpress.MSO.ADXAddinModule
#Region " Add-in Express automatic code "
[…]
#End Region
Public Shared Shadows ReadOnly Property CurrentInstance() As AddinModule
Get
Return CType(AddinExpress.MSO.ADXAddinModule.CurrentInstance, AddinModule)
End Get
End Property
Public ReadOnly Property PowerPointApp() As PowerPoint._Application
Get
Return CType(HostApplication, PowerPoint._Application)
End Get
End Property
Private Sub AdxRibbonButton2_OnClick(sender As Object, control As IRibbonControl, pressed As Boolean) Handles AdxRibbonButton2.OnClick
MsgBox(GetInfoString2())
End Sub
Friend Function GetInfoString2() As String
Dim ActiveWindow As Object = Nothing
Try
ActiveWindow = Me.HostApplication.ActiveWindow()
Catch
End Try
Dim Result As String = "No document window found!"
If Not ActiveWindow Is Nothing Then
Select Case Me.HostType
Case ADXOfficeHostApp.ohaPowerPoint
Dim Selection As PowerPoint.Selection =
CType(ActiveWindow, PowerPoint.DocumentWindow).Selection
Dim WindowViewType As PowerPoint.PpViewType = PowerPoint.PpViewType.ppViewNormal
Dim SlideRange As PowerPoint.SlideRange = Selection.SlideRange
Dim SlideCountString = SlideRange.Count.ToString()
If WindowViewType = 9 And SlideCountString < 2 Then
Dim ShRange As PowerPoint.ShapeRange = Nothing
Try
ShRange = Selection.ShapeRange
Catch
End Try
If Not ShRange Is Nothing Then
Dim ShapeCount = ShRange.Count.ToString()
Result = "You have " + ShapeCount _
+ " shapes selected."
Else
Result = "You have 0 shapes selected."
End If
End If
'Marshal.ReleaseComObject(ShapeCount)
'Marshal.ReleaseComObject(ShRange)
'Marshal.ReleaseComObject(WindowViewType)
'Marshal.ReleaseComObject(SlideCountString)
Marshal.ReleaseComObject(SlideRange)
Marshal.ReleaseComObject(Selection)
Case Else
Result = AddinName + " doesn't support " + HostName
End Select
'Marshal.ReleaseComObject(Me.HostType)
'Marshal.ReleaseComObject(Result)
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
Marshal.ReleaseComObject(Me.HostApplication)
'Marshal.ReleaseComObject(Me)
End If
Return Result
End Function
End Class
FinalReleaseComObject
调用 ReleaseComObject
直到 returns 0,这意味着释放 COM 对象。以相反的顺序调用它们,如 Excel objects(Application, Workbook, Worksheet) 是处理相关 COM 对象的正确方法。
Exception Condition
ArgumentException
o is not a valid COM object.ArgumentNullException
o is null.
Marshal class 的 ReleaseComObject 方法减少与指定 COM 对象关联的指定运行时可调用包装器 (RCW) 的引用计数,它不会释放对象。它来自 COM 性质。
通常您需要释放从 Office(在您的例子中是 PowerPoint)对象模型返回的每个对象。异常是作为参数传递给事件处理程序的对象。
您可以阅读更多相关内容并在 When to release COM objects in Office add-ins developed in .NET 文章中找到您的多个问题的答案。