Matthew Wills @ Readify

May 19, 2008

COM Interop Principle #1 – Don’t Cheat

Filed under: COM Interop, Technical — mjwills @ 12:22 pm

This post is the second in my series on getting your head around COM Interop. My aim here is not to teach you all the innards of COM Interop, but instead to communicate a few key principles. These principles will (hopefully) make your life a little simpler when coding in .NET against COM components (particularly in relation to getting the COM objects to clean themselves up).

COM Interop Principle #1: Don’t Cheat (by relying on the Garbage Collector)

In my previous post, I listed a short code sample that was not behaving as I might have liked. Specifically, it was not closing down Excel when I wanted it to. In that post I called for attempts to get the code ‘working’ without calls to GC.Collect().

But, what if you ignored my requirement to not use GC.Collect()? Well, you would likely have come up with a solution something like this:

Option Strict Off
Option Explicit On
Imports msE = Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices
Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim wb As msE.Workbook
        Dim ws As msE.Worksheet
        Dim xlApp As msE.Application
        '==========================
        xlApp = New msE.Application
        xlApp.DisplayAlerts = False
        xlApp.Interactive = False
        xlApp.Workbooks.Add()
        wb = xlApp.Workbooks(1)
        'Clear all but the first worksheet
        For Each wrk As msE.Worksheet In wb.Worksheets
            If wrk.Index > 1 Then wrk.Delete()
        Next
        ws = wb.Sheets(1)
        xlApp.Visible = True
        Threading.Thread.Sleep(5000)    'So we can see Excel
        wb.Close(False)
        xlApp.Quit()
        Marshal.ReleaseComObject(ws)
        Marshal.ReleaseComObject(wb)
        Marshal.ReleaseComObject(xlApp)
        GC.Collect()
        GC.Collect()' A couple more for good measure
        GC.Collect()' A couple more for good measure
        GC.WaitForPendingFinalizers()

    End Sub
End Class

So, what is the problem?

There are two:

  1. It doesn’t work (well, not on my machines running Visual Studio 2008 on Vista 32-bit, nor my machines running Visual Studio 2003 on XP 32-bit).
  2. Even if it did work on your PC (or in your version of the .Net Framework) there is no guarantee that it would work in the future or on other machines.

So:

COM Interop Principle #1: Don’t Cheat (by relying on the Garbage Collector)

As with all principles, there are exceptions! Such as:

  • If the lifetime of your RCWs (COM components) is the same as your application (eg you will be loading Excel when your application starts, and closing it when your application closes) then there is little point in cleaning up correctly. You can be confident (not 100% sure, but confident) that all RCWs will be cleaned up when your process shuts down. So, cheating is OK. :)

Coming up next – COM Interop Principle #2: Fear the Period.

1 Comment »

  1. [...] week’s post was about what not to do when dealing with COM [...]

    Pingback by COM Interop Principle #2 - Fear the Period « Matthew Wills @ Readify — May 26, 2008 @ 12:37 pm


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.