Office アプリケーションが Visual Studio .NET クライアントからオートメーションの後に終了しません。

現象

Microsoft Visual Basic .NET または Microsoft Visual C# .NET から Microsoft Office アプリケーションを自動化すると、Office アプリケーションは、 Quitメソッドを呼び出すと終了しません。

原因

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

解決策

Office アプリケーションが終了することを確認するのには、オートメーションのコードが次の条件を満たしていることを確認します。
  • 各オブジェクトを新しい変数として宣言します。たとえば、次のコード行を変更します。
    oBook = oExcel.Workbooks.Add()
    次。
    dim oBooks as Excel.WorkbooksoBooks = oExcel.Workbooks
    oBook = oBooks.Add()

  • オブジェクトを使用して終了すると 0 を返すまでループ内でSystem.Runtime.InteropServices.Marshal.ReleaseComObjectを使用します。System.Runtime.InteropServices.Marshal.ReleaseComObject減っていきますが、RCW、およびループの参照カウントは、方法に関係なく、基になる COM コンポーネントがリリースされたことにより、何度も、再入力した CLR。
  • 変数への参照を解放するには、 NothingまたはNull変数等を設定します。
  • サーバをシャット ダウンを確認するのにには、Office アプリケーション オブジェクトのQuitメソッドを使用します。

状況

これは仕様による動作です。

詳細

現象を再現する手順を実行します。

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

      Microsoft Excel 2002: Microsoft Excel 10.0 オブジェクト ライブラリ

      注: されていない場合は、ダウンロードして、Microsoft Office XP プライマリ相互運用機能アセンブリ (Pia) をインストールすることをお勧めします。

      Office XP Pia の詳細については、マイクロソフト サポート技術情報の記事を表示するのには次の資料番号をクリックします。

      328912 Microsoft Office XP プライマリ相互運用機能アセンブリ (Pia) は、ダウンロード可能な

      Microsoft Office Excel 2003: Microsoft Excel 11.0 オブジェクト ライブラリ
    3. 選択を確定参照の追加] ダイアログ ボックスで[ok]をクリックします。
  4. [表示] メニューで、[ツールボックス] をクリックし、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
    While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
    End While
    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
{
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
}
catch {}
finally
{
o = null;
}
}

注:.NET Framework 2.0 以降を使ってSystem.Runtime.InteropServices.Marshal.FinalReleaseComObjectしばらくの間ではなく同じ結果を達成するために呼び出し元のSystem.Runtime.InteropServices.Marshal.ReleaseComObjectをループします。

トラブルシューティング

」「問題の再現手順」セクションに記載されている手順を実行したサーバーがシャット ダウンしない場合、は、 GC を使用することに注意してください。Collect() を使用してメソッドとの GC。WaitForPendingFinalizers()メソッドの最後のオブジェクトを解放した後。ランタイムは、 GC、RCW でガベージ コレクションを実行します。Collect() を使用してメソッドは、強制的にガベージ コレクターが実行し、RCW が保持している参照を解放します。GC です。Collect() を使用してメソッドが使用可能な最大メモリを解放しようとしました。すべてのメモリを再利用されることは保証されないことを確認します。
プロパティ

文書番号:317109 - 最終更新日: 2017/02/01 - リビジョン: 1

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

フィードバック