私は C# ( ) で Excel 相互運用機能を使用しておりApplicationClass
、finally 句に次のコードを配置しています。
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet) != 0) { }
excelSheet = null;
GC.Collect();
GC.WaitForPendingFinalizers();
この方法はうまく機能しますが、Excel.exe
Excel を閉じた後もプロセスはバックグラウンドで実行されます。アプリケーションを手動で閉じたときにのみ解放されます。
何が間違っているのでしょうか、それとも相互運用オブジェクトが適切に破棄されるようにする代替手段があるのでしょうか?
ベストアンサー1
アプリケーションが COM オブジェクトへの参照を保持しているため、Excel は終了しません。
COM オブジェクトの少なくとも 1 つのメンバーを変数に割り当てずに呼び出しているようです。
私の場合は、変数に割り当てずに直接使用したexcelApp.Worksheetsオブジェクトでした。
Worksheet sheet = excelApp.Worksheets.Open(...);
...
Marshal.ReleaseComObject(sheet);
私は、C# が内部的にWorksheets 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 つのドット」の道をたどらないようにしてください。.NET でのガベージ コレクションを理解するそしてIDisposable を使用して Excel 相互運用オブジェクトをクリーンアップする