1. ホーム
  2. c#

[解決済み] Excel の相互運用オブジェクトを適切にクリーンアップするにはどうすればよいですか?

2022-03-21 04:56:40

質問

C#でExcelのinteropを使っているのですが、( ApplicationClass ) そして、以下のコードをfinally節に配置しました。

while (System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet) != 0) { }
excelSheet = null;
GC.Collect();
GC.WaitForPendingFinalizers();

このように動作するものの Excel.exe プロセスは、Excel を閉じた後もバックグラウンドに残っています。このプロセスは、私のアプリケーションを手動で閉じたときにのみ解放されます。

または、相互運用オブジェクトを適切に破棄するための代替手段がありますか?

解決方法は?

アプリケーションがCOMオブジェクトへの参照を保持したままになっているため、Excelが終了しない。

COMオブジェクトの少なくとも1つのメンバーを変数に代入せずに呼び出しているのでしょう。

私の場合、それは excelApp.Worksheets オブジェクトを変数に代入することなく直接使用しました。

Worksheet sheet = excelApp.Worksheets.Open(...);
...
Marshal.ReleaseComObject(sheet);

C#が内部的に ワークシート COMオブジェクトは私のコードでは解放されず(私が気づいていなかったため)、Excelがアンロードされない原因となっていました。

この問題の解決策は このページ また、C#でのCOMオブジェクトの使用に関する素晴らしい規則もあります。

COM オブジェクトにドット 2 つを使用しないでください。


つまり、この知識を持ってすれば、上記の正しい方法は

Worksheets sheets = excelApp.Worksheets; // <-- The important part
Worksheet sheet = sheets.Open(...);
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);

死後の更新

このHans Passantの回答は、私や他の多くの開発者がつまずいた罠を説明しているので、すべての読者に注意深く読んでほしいです。数年前にこの回答を書いたとき、私はデバッガがガベージコレクタに与える影響について知らなかったので、間違った結論を出してしまったのです。私は歴史のために私の答えをそのままにしていますが、このリンクを読んでください。 ドンマイ 2つの点(quot;the two dots")の道を歩む。 .NETのガベージコレクションを理解する IDisposableでExcel Interopオブジェクトをクリーンアップする