1

I have just started to migrate some code from VBA to VB.Net. So I am an absolute beginner in VB.Net – but I want to do things right. Maybe some of my questions are stupid but I guess that is because I am a beginner.

So as a first exercise I have developed my first piece of code (see below). Now I thought I have to release ALL COM objects again. Two of them throw errors already while writing the code. And others throw errors at runtime.

But the funny thing is: Weather I release the rest of the COM objects or not (by making the relevant not yet commented lines of Marshal.Release to comments as well – then all lines starting with Marshal.Release are comment lines) the behavior of the code is absolutely the same to my eyes.

Can anybody tell me where I can see/find the difference?

The internet tells me that there must be a difference? But I guess I just don’t understand (till now).

Besides this many more questions are in my head:

  1. Does every “Dim” statement create a COM Object - that has to be released later on?
  2. If not how do I detect whether a COM object has been created or not? Which “Dim” statements create COM object and which don't?
  3. In this example: Dim ActiveWindow As Object = Nothing Try ActiveWindow = Me.HostApplication.ActiveWindow() Catch End Try

Is

Marshal.ReleaseComObject(ActiveWindow) identical to Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())?

  1. According to this:

http://www.codeproject.com/Tips/235230/Proper-Way-of-Releasing-COM-Objects-in-NET

Would it not be better to release each "level" separately like this:

Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
Marshal.ReleaseComObject(Me.HostApplication)
Marshal.ReleaseComObject(Me)
  1. Overall: Am I trying to release too much? Or is it correct / good practie?

  2. And what does "GC.Collect()" and "… = Null" have to do with all this? I have not used it at all. Should I better use it? Why? ( "... = Null" I have seen here:

http://www.codeproject.com/Tips/162691/Proper-Way-of-Releasing-COM-Objects-in-NET)

  1. Why do I get “ShapeCount was not declared …” - Error if I try to do “Marshal.ReleaseComObject(ShapeCount)”? The same with “ShRange”. I think these are COM objects as well?!?

  2. How do I notice when is the best time to release the COM object again? When I process/debug my code step by step with F11 will it be possible for me to determine the best (soonest) point of release? So far I have no “feeling” about when the COM object is not needed anymore and I can release it.

Any help and explanations very welcome.

Here is the code I am talking about:

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
DrS.
  • 67
  • 2
  • 12
  • Many thanks for the answers. I have optimized my code like you can see here [link] https://support.microsoft.com/de-de/kb/317109 [link]. Now I have a different queston on my mind. Why does msdn uses `ByVal` for the private sub `Private Sub NAR(ByVal o As Object)`. Personally I would use ByRef as I have seen it here: [link] http://stackoverflow.com/questions/12916137/best-way-to-release-excel-interop-com-object [link] or does it not make any difference? – DrS. Nov 10 '15 at 12:48

2 Answers2

1

The ReleaseComObject method of the Marshal class decrements the reference count of the specified Runtime Callable Wrapper (RCW) associated with the specified COM object, it doesn't release an object. It comes from the COM nature.

Typically you need to release every object returned from the Office (PowerPoint in your case) object model. Exceptions are objects passed to event handlers as parameters.

You may read more about that and find answers to your multiple questions in the When to release COM objects in Office add-ins developed in .NET article.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
0

FinalReleaseComObject calls ReleaseComObject til it returns 0 which means release of COM object. Calling them in reverse order as in Excel objects(Application, Workbook, Worksheet) is the proper way to dispose of COM objects that are related.

Exception Condition

ArgumentException
o is not a valid COM object.

ArgumentNullException
o is null.

OneFineDay
  • 9,004
  • 3
  • 26
  • 37
  • Many thanks for your answer. I am not sure if I understand how to make use of your answer? I have still too many questions in my head to see clear. Many thanks for any further help. – DrS. Oct 23 '15 at 10:21
  • If simply replacing your ReleaseComObject method with my suggestion does not work then you have deeper issues. If your class is a COM object you can't release it from inside itself. – OneFineDay Oct 23 '15 at 14:34