文書番号: 317109 - 最終更新日: 2005年6月10日 - リビジョン: 4.1

Visual Studio .NET クライアントで自動化した Office アプリケーションが終了しない

目次

すべて展開する | すべて折りたたむ

現象

Microsoft Visual Basic .NET または Microsoft Visual C# .NET で Microsoft Office アプリケーションを自動化した場合に、Quit メソッドを呼び出しても Office アプリケーションが終了しません。

原因

Visual Studio .NET でマネージ コードから COM オブジェクトを呼び出すと、自動的にランタイム呼び出し可能ラッパー (RCW) が作成されます。RCW は、.NET アプリケーションと COM オブジェクトの間の呼び出しをマーシャリングします。RCW は、COM オブジェクトへの参照カウントを保持します。したがって、RCW でのすべての参照が解放されていない場合、COM オブジェクトは終了しません。

解決方法

Office アプリケーションを終了するには、オートメーション コードが以下の条件を満たしていることを確認してください。
  • 各オブジェクトを新しい変数として宣言しています。たとえば、コードに次の行があるとします。
    oBook = oExcel.Workbooks.Add()
    					
    この行を次のように変更します。
    dim oBooks as Excel.Workbooks
    oBooks = oExcel.Workbooks
    oBook = oBooks.Add()
    					
  • オブジェクトの使用が終了したら、System.Runtime.InteropServices.Marshal.ReleaseComObject を使用します。このメソッドによって RCW の参照カウントを減らします。
  • 変数を Nothing または Null に設定して、変数への参照を解放します。
  • Office アプリケーション オブジェクトの Quit メソッドを使用して、サーバーにシャットダウンするように指示します。

状況

この動作は仕様です。

詳細

現象の再現手順

  1. Visual Studio .NET を起動します。
  2. [ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。[Visual Basic プロジェクト] をクリックし、[Windows アプリケーション] をクリックして、[OK] をクリックします。Form1 がデフォルトで作成されます。
  3. Microsoft Excel Object Library への参照を追加します。この操作を行うには、以下の手順を実行します。
    1. [プロジェクト] メニューの [参照の追加] をクリックします。
    2. [COM] タブで、Excel 用のオブジェクト ライブラリを探してクリックし、[選択] をクリックします。

      Microsoft Excel 2002 の場合 : Microsoft Excel 10.0 Object Library

      : Microsoft Office XP プライマリ相互運用機能アセンブリ (PIA) をまだ入手していない場合は、ダウンロードしてインストールすることをお勧めします。 Office XP 用の PIA の関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
      328912? (http://support.microsoft.com/kb/328912/ ) [INFO] Microsoft Office XP 用の PIA のダウンロード
      Microsoft Office Excel 2003 の場合 : Microsoft Excel 11.0 Object Library
    3. [参照の追加] ダイアログ ボックスで [OK] をクリックして選択内容を確定します。
  4. [表示] メニューの [ツールボックス] をクリックし、Button コントロールを Form1 にドラッグします。
  5. [Button1] をダブルクリックします。フォームのコード ウィンドウが表示されます。
  6. Form1.vb の先頭に次のコードを追加します。
    Imports Microsoft.Office.Interop
    					
  7. コード ウィンドウには、次のコードが表示されています。
        Private Sub Button1_Click(ByVal sender As System.Object, _
           ByVal e As System.EventArgs) Handles Button1.Click
        End Sub
    					
    これを次のコードで置き換えます。
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim oApp As New Excel.Application()
        Dim oBook As Excel.Workbook = oApp.Workbooks.Add
        Dim oSheet As Excel.Worksheet = oApp.ActiveSheet
        oSheet = Nothing
        oBook.Close(False)
        oBook = Nothing
        oApp.Quit()
        oApp = Nothing
        Debug.WriteLine("Sleeping...")
        System.Threading.Thread.Sleep(5000)
        Debug.WriteLine("End Excel")
    End Sub
    					
  8. F5 キーを押してアプリケーションを実行します。
  9. Windows タスク マネージャを起動します。Visual Studio で [出力] ウィンドウを表示して、デバッグ メッセージを参照します。コマンド ボタンをクリックすると、Excel.exe のインスタンスが [プロセス] タブの一覧に表示されることを確認します。
  10. アプリケーションが休止を終了した後も、タスク マネージャの一覧で Excel のインスタンスが実行されています。ダイアログ ボックスを閉じると、Excel が [プロセス] タブの一覧に表示されなくなることを確認します。
  11. 「解決方法」に記載した手順を実行すると、Office アプリケーションは最後の変数の解放後、終了します。手順 5. の関数を次のコードで置き換えます。
      Private Sub NAR(ByVal o As Object)
        Try
          System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
        Catch
        Finally
          o = Nothing
        End Try
      End Sub
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim oApp As New Excel.Application()
        Dim oBooks As Excel.Workbooks = oApp.Workbooks
        Dim oBook As Excel.Workbook = oBooks.Add
        Dim oSheet As Excel.Worksheet = oApp.ActiveSheet
        NAR(oSheet)
        oBook.Close(False)
        NAR(oBook)
        NAR(oBooks)
        oApp.Quit()
        NAR(oApp)
        Debug.WriteLine("Sleeping...")
        System.Threading.Thread.Sleep(5000)
        Debug.WriteLine("End Excel")
    End Sub
    					
Visual C# .NET を使用している場合は、NAR() 関数のコードを参照します。
private void NAR(object o)
{
    try 
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
    }
    catch {}
    finally 
    {
        o = null;
    }
}

トラブルシューティング

「現象の再現手順」で説明した手順を実行してもサーバーがシャットダウンしない場合は、最後のオブジェクトの解放後、GC.Collect() メソッドと GC.WaitForPendingFinalizers() メソッドを使用します。ランタイムは RCW でガベージ コレクションを実行するため、GC.Collect() メソッドはガベージ コレクタを強制的に実行し、RCW が保持している参照を解放します。GC.Collect() メソッドは、使用可能なメモリの最大メモリを要求しますが、すべてのメモリが利用可能になるわけではないことに注意してください。

関連情報

この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID 317109? (http://support.microsoft.com/kb/317109/EN-US/ ) (最終更新日 2004-09-03) を基に作成したものです。

この資料に含まれているサンプル コード/プログラムは英語版を前提に書かれたものをありのままに記述しており、日本語環境での動作は確認されておりません。

この資料は以下の製品について記述したものです。
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual Basic .NET 2002 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
キーワード:?
kbautomation kbprb KB317109
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"
 

サポート技術情報の翻訳