玄関へお回り下さい。
Excelのプロセスが正常に終了しない理由(その1)
.NET 対応の Visual Basic から Excel VBA を使って、Visual Basic から Excel を操作した場合、タスクマネージャーに Excel.exe が残ったままになる事が、VB6.0 の頃よりはるかに多く発生しております。
この事は、
サポート情報の[Visual Studio .NET クライアントで自動化した Office アプリケーションが終了しない]にも書かれているように、COM オブジェクト参照すると参照カウントが一つアップします。
参照が解放された時に参照カウントが一つ減り参照カウントが、0 の時でないとCOM オブジェクトは終了しません。
従って、COM オブジェクトを使用後は、プログラム上から、Marshal.ReleaseComObject メソッド 等を使って参照カウントデクリメント(参照カウントを 1減じる処理)する必要があります。

ここで言うCOM オブジェクトとはどのような物が該当するのかを知っておく必要がありますので、下記にまとめて見ました。
COM オブジェクト 及び Com オブジェクト等を返すプロパティ 一覧

そこで問題になるのが、上記のようなCOM オブジェクトを使用した場合は、使用するCOM オブジェクト1個対して夫々デクリメント操作が必要なのに、複数のCOM オブジェクトを同時に参照すると、どれか1個だけしかデクリメントができません。


例えば、フォントを太字にする場合、VBA や VB6.0 では、xlSheet.Range("A1").Font.Bold = True のような書き方が一般的でした。
これをVB.NET(便宜上.NET系のVisual Basicをこう書かせて頂きます)で使用すると Excel.exe がプロセスに残ってしまいます。
そこで、使用したCom オブジェクトに対して各々デクリメントしてやる必要があります。
デクリメントするには、Com オブジェクト を変数に受けて使用し、使い終わった時点で、Marshal.ReleaseComObject メソッドを使って使用したCom オブジェクト の変数に対してデクリメントする必要があります。
xlSheet(Worksheet オブジェクトを変数にうけたもの) Range Font の3つのCom オブジェクトを使った事になりますからそれぞれのCom オブジェクトを別々に変数に受けて使用しないとデクリメント操作ができません。
従って、xlSheet は、すでに変数にうけたものですから必要はありませんが、
 Range や Font は、一旦変数に受けて使用する必要があり、従って、VB.NET 用にコードを書くと下記のようになります。

   Dim xlRange As Excel.Range       '使用する Range オブジェクト用の変数を宣言する
   
xlRange = xlSheet.Range("A1")    'Range オブジェクト用の変数に、Range("A1") を代入する
   Dim 
xlFont As Excel.Font         '使用する Font オブジェクト用の変数を宣言する
   
xlFont = xlRange.Font            'Font オブジェクト用の変数に、Range("A1")の Font を代入する
   
xlFont.Bold = True               'Range("A1")の Font の Bold プロパティを太字に設定する
   
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlFont)   'Font(xlFont) オブジェクトのデクリメントの実施 
   
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange)  'Range(xlRange) オブジェクトのデクリメントの実施 

上記のように使用した夫々の Com オブジェクトは、変数に受けて、その変数に対してデクリメントしないと Com オブジェクトは終了せず、Excel を閉じても、タスクマネージャーのプロセス一覧のところに、Excel.exe が残ったままになるのです。

ここで、問題になるのが、どれが、Com オブジェクトでいつデクリメントする必要があるのかと言う事になります。
COM オブジェクト及び Com オブジェクト等を返すプロパティ等を知っておく事は無論の事、Cells プロパティのような Default プロパティがある Com オブジェクトを返すプロパティ等を使用した場合、つい下記のように使ってしまいがちですが、これでは、十分にデクリメントがされず、解放されません。

   Dim xlCells As Excel.Range
   'xlCells = xlSheet.Cells(1, 1)    'Strict On では、暗黙的な変換はできません とエラー表示になる
   
xlCells = DirectCast(xlSheet.Cells(1, 1), Excel.Range)  '従って、このように型変換する
   Dim 
xlFont As Excel.Font
   
xlFont = xlCells.Font
   
xlFont.Bold = True
   
MRComObject(xlFont)   'Font(xlFont) オブジェクトのデクリメントの実施 
   
MRComObject(xlCells)  'Range(xlCells) オブジェクトのデクリメントの実施 

xlSheet.Cells(1, 1) は、Default プロパティ 省略した書き方なので、正しくは、
xlsheet.Cells._Default(1, 1)
又は、xlSheet.Cells.Item(1, 1) となり、Cells が返す Range オブジェクトと_Default が返すRange オブジェクトを別々に変数に受けてデクリメントしないと解放されません。(正しくは、下記のようになります。)

   Dim xlCells As Excel.Range
   Dim 
xlRange As Excel.Range
   
xlCells = xlSheet.Cells
   
xlRange = DirectCast(xlCells.Item(1, 1), Excel.Range)
   Dim 
xlFont As Excel.Font
   
xlFont = xlRange.Font
   
xlFont.Bold = True
   
MRComObject(xlFont)
   
MRComObject(xlRange)
   
MRComObject(xlCells)
 
このように一旦、Range オブジェクトに変換しなければならず、VB6.0 や VBA のような使い方ができず、コードも複雑になるし、なにより間違った使い方をすると解放漏れの恐れがあり、Cells プロパティのようなDefault プロパティのある、Rangr オブジェクトを返す、プロパティのご使用はお薦めできません。
(どうせ、Range オブジェクトに変換するなら、最初からRange オブジェクトを使うべきかと)
このようなDefault プロパティを返すプロパティは、他にも色々ありますので注意して下さい。
見分け方としては、Com オブジェクトを返すプロパティの中で、最後に複数系を表す s がついているプロパティで、メンバーに、Item プロパティが存在するようなものは、十分確認して下さい。
代表的なものとしては、Workbooks Sheets Cells Rows Columns 等があります。

もう一つの問題点のいつデクリメントする必要があるのかと言う事ですが、基本的には、[使い終わった時点]と言う事になりますが、それは、変数のスコープを指しているのと勘違いしている場合がありますが、参照先を変更した場合等にも摘要されます。

下記のような場合、どの位置でデクリメントを実施すべきでしょうか?
   Dim xlRange As Excel.Range = Nothing
   
xlRange = xlSheet.Range("A1")
   
xlRange.Value = "123"
   Dim 
xlFont As Excel.Font
   
xlFont = xlRange.Font
   
xlFont.Bold = True
   
xlRange = xlSheet.Range("A2")
   
xlRange.Value = "321"
   
xlFont = xlRange.Font
   
xlFont.Bold = True
   For c As Integer = 1 To 10
      
xlRange = xlSheet.Range(R1ToA1(1, c))
      
xlRange.Value = c
   Next c

正しくは、下記のようになります。

   Dim xlRange As Excel.Range = Nothing
   
xlRange = xlSheet.Range("A1")
   
xlRange.Value = "123"
   Dim 
xlFont As Excel.Font
   
xlFont = xlRange.Font
   
xlFont.Bold = True
   
MRComObject(xlFont)
   
MRComObject(xlRange)
   '次の行で、xlRange は、A1 を参照していたのに、A2 に参照先が変わるので変わると
   'xlRange は、Range("A1") ではなくなり、xlRange をデクリメントしてもRange("A1") の
   'Com オブジェクトのデクリメントは、行われず解放できなくので参照先が変更される前に
   '上記の行でデクリメントをしておく必要があります。
   
xlRange = xlSheet.Range("A2")
   
xlRange.Value = "321"
   
xlFont = xlRange.Font
   
xlFont.Bold = True
   
MRComObject(xlFont)     '同様に Font オブジェクトも参照先が変更されたので
   
MRComObject(xlRange)    '同様にここでも
   For c As Integer = 1 To 10
      
xlRange = xlSheet.Range(R1ToA1(1, c))
      
xlRange.Value = c
      
MRComObject(xlRange) '同様にここでも
   Next c

これが、ここで言う[使い終わった時点]と言う事です。
上記のコードは、実際にご自分で十分に試して見て頭に叩き込んでおいて下さい。
どれが、Com オブジェクトでいつデクリメントする必要があるのかと言う事を十分理解してコードを書けば、Excel.exe がプロセスに残るという事はなくなるはずです。

その他、VB.NET(VB2005/VB2008/VB2010) 系からExcel を操作する上での注意事項をまとめてみました。

1.開発環境は、参照設定をして、事前バインディング(アーリーバインディング)で使用し、
  Option Strict On に設定した、VB2010(VB2008) 以上で開発するようにして下さい。
  事前バインディングで使用されると解放もれが発生し易く、原因も掴めにくかったりもしますので、
  掲示板で質問されるようなレベルの方は、絶対に使用されない事をお薦めします。
  (自分で問題解決ができるのなら別ですが)

2.次に、起動・終了だけの基本的なプログラムを書いた時点でテストしてプロセスが終了している
  か確認しておく
  開発中は、下記のようなコードで、起動・終了をしながらテストすると便利です。
  (サンプル投稿用掲示板に投稿してある起動・終了用コード)

3.コードはマクロ等をそのままペーストせず、キーボードから入力する
  (そうする事によって自動メンバー表示やパラメーターヒントが表示される)
  特に、VB2010 等を使用するとエラーの修正機能があったりとかで,VB2005 等よりかなり便利に
  なっております。

4.自動メンバー表示等が表示されない場合は、コードの使い方が間違っている場合があるので
  ヘルプ等で確認する事。

5.今までと違った使い方や使った事のないプロパティ等を使用した場合は、その時点でプロセスが
  終了するか確認しておく

6.コードの区切りの時点でそこまでの動作でプロセスがきちんと終了する事を確認しながら進める

以上の6項目を守れば少なくとも、他人に間違い探しを依頼する事はないはずです。
作ってしまってからプロセスが終了していない事に気が付いたのなら、確認できている部分を除いてコメント化して、確認しながら順次コメントを外して原因箇所を掴んで下さい。

下記のようなツールを作成しておくと結構便利かと思います。

 Excel Com オブジェクトの解放漏れチェックツール(試作版)

 下記のカラー太字で表示されている部分が解放漏れになっている部分です。
  http://hanatyan.sakura.ne.jp/dotnet/comtest.htm

従って、上記で、カラー太字で表示されているようなコードは、VB.NET(VB2005/VB2008/VB2010) 系では使ってはいけないコードになります。
実際のCOM オブジェクトの使い方については、当サイトサンプルやTips が掲載してありますし、掲示板の過去ログにも色々掲載がありますので参考にして下さい。
1.VB2005用掲示板の過去のログの閲覧ツール
2.サンプル投稿用掲示板VB2010からExcelを操作するためのワンポイントテクニック集(VB.NET)
3.サンプル投稿用掲示板カテゴリ別表示


2005/04/02
2008/11/05
2012/05/21
2012/06/09

VBレスキュー(花ちゃん)
VB.NET2003/VB2005/VB2008/VB2010
Excel 2007/Excel 2010/Excel VBA