.netから Excel Comオブジェクトを利用するときにExcelを正常に終了させる方法

http://blogs.timberlandchapel.com/blogs/timberlandchapel/articles/1149.aspx

使用した COM オブジェクトは必ず解放しなければいけない。

COM オブジェクトの解放は,「System.Runtime.InteropServices.Marshal.ReleaseComObject」を使用します。
COM オブジェクトの解放
System.Runtime.InteropServices.Marshal.ReleaseComObject( [COM オブジェクト] )

ループ内で使用する,変数を共有するオブジェクトは都度解放する。

[ReleaseComObject] は,インスタンス化したオブジェクトの数だけ行わなければいけません。
ループ内で [Worksheet] オブジェクトを複数回使用する場合は,変数に格納した数だけ解放する必要があります。
COM オブジェクトの解放
For counter As Int32 = 0 To 10
myWorksheet = myWorkbooks.Item(counter)
System.Runtime.InteropServices.Marshal.ReleaseComObject(myWorksheet)
Next

「.(ドット)」を使用して,プロパティやメソッドを経由して呼び出してはいけない。

[Application] クラスの [Workbooks] プロパティなどがこれにあたります。
これらのプロパティは適切な変数に経由して,経由したオブジェクトも [ReleaseComObject] を呼び出さなければいけません。
このルールは見落としがちです。
プロパティ,メソッドの経由呼び出しの回避
Dim myExcel As New Microsoft.Office.Interop.Excel.Application
Dim books As Microsoft.Office.Interop.Excel.Workbooks

books = myExcel.Workbooks
book = books.Add

Cells プロパティではなく,Range プロパティを使用する。

セルの値を書き換える場合などに,[Worksheet] クラスの [Cells] プロパティを使用して,行と列を指定した(R1C1形式)セルを取得することができます。
この [Cells] プロパティは [Range] クラスに DirectCast することによって値の操作が可能になります。
しかし,[Cells] プロパティから [Range] への変換を使用していると,Excel プロセスが正しく解放されません。
セルの名称(A1形式)を指定する [Range] プロパティを使用します。
[Range] プロパティの使用
Dim targetRange As Range

' Cells では解放されない
targetRange = DirectCast(myWorksheet.Cells(3, 1), Range)

' Range は正しく動作する
targetRange = myWorksheet.Range("A3")

特にCellsを使うと開放されなくなるってのは意味不明なので気づきにくい。注意。
Comオブジェクトの参照カウンタが0にされないってのが開放されない原因のハズなのに、なぜCellsメソッド使っただけでExcelオブジェクトが開放されなくなるかな……。