2016-04-25 10 views
1

私は確かに私のCOMオブジェクトはので、私は、バックグラウンドで実行されているEXCEL.EXEプロセスを残していない午前閉じている作りに苦労しています。私は宣言の二重点と連鎖が悪いことを知っています。これは、COMオブジェクトをぶら下げてしまう可能性があるからです。Microsoft.Office.Interop.Excel.Worksheetを宣言してC#で閉じることができますか?

誰もがそう私ができる適切に閉じ、ワークシートのCOMオブジェクトを解放のコード行を修正する方法を知っていますか?

worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets[strName]; 

編集:私は、しかし、これは動作しません、私は開いているExcelオブジェクトを閉じるには、この行を実行し終わっていたときにapp.Quit()を使用して試してみました。 app.Quit()私はこの行の前にしかし、それを呼び出す場合は動作します。 EXCEL.EXEのプロセスを聞かせするために、すべての

答えて

4

まず、あなたが明示的に使用されているすべてのCOMオブジェクトを解放する必要はありません終了します。 COMオブジェクトへの別の参照を取得したときに.NETランタイムによって暗黙的に作成された実行時呼び出し可能ラッパー(RCW)は、GCによって収集され、これが基になるCOMオブジェクトを解放します。

あなたがしなければならないのは、Quitメソッドを呼び出しRCWS参照を解放し、GCがそれらを収集できるようにすることです。

//This runs the EXCEL.EXE process. 
Microsoft.Office.Interop.Excel.Application app = 
    new Microsoft.Office.Interop.Excel.Application(); 
//This locks the excel file either for reading or writing 
//depending on parameters. 
Microsoft.Office.Interop.Excel.Workbook book = app.Workbooks.Open(...); 

... 

//Explicitly closing the book is a good thing. EXCEL.EXE is alive 
//but the excel file gets released. 
book.Close(); 

//This lets the EXCEL.EXE quit after you release all your references to RCWs 
//and let GC collect them and thus release the underlying COM objects. 
//EXCEL.EXE does not close immediately after this though. 
app.Quit(); 
app = null; 

第2に、いわゆるダブルドットコード行を残しておくと、メモリリークが発生しません。ガベージコレクタはRCWを収集し、いつか、それが正しいと判断したときにCOMオブジェクトを解放する。

最後にRCWと対応するCOMオブジェクトを明示的に解放してメモリの負担を最小限に抑えたい場合は、GCWを参照してRCWを参照することができます。 GCの前にCOMオブジェクトはRCWを収集します。しかし、注意してください。この最後の方法は、残っているRCWがそれ以降使用されない、または例外が発生するという事実をあなたに任せます。

using Microsoft.Office.Interop.Excel; 
using System.Runtime.InteropServices; 

Application app = new Application(); 
Workbooks books = clsExcelApplication.Workbooks; 
Workbook book = books.Open("..."); 
Sheets sheets = book.Sheets; 
Worksheet sheet = sheets["..."]; 

... 

//Trying to be as explicit as we can. 
book.Сlose(); 

//Revese order. Using FinalReleaseComObject is even more dangerous. 
//You might release an object used inside excel 
//code which might lead to some dreadful internal exceptions. 
int remainingRefCount; 
remainingRefCount = Marshal.ReleaseComObject(sheet); 
remainingRefCount = Marshal.ReleaseComObject(sheets); 
remainingRefCount = Marshal.ReleaseComObject(book); 
remainingRefCount = Marshal.ReleaseComObject(books); 
app.Quit(); 
remainingRefCount = Marshal.ReleaseComObject(app); 

注意してください。手動でEXCEL.EXE寿命がRCWSに依存しないよりも、COMの参照を解放し、あなたが好きなときに最も明白な場合は...

sheet = null; 
sheets = null; 
book = null; 
books = null; 
app = null; 

それらを無効にすることができた場合は、からの復帰をチェックすることを忘れないでくださいMarshal.ReleaseComObject。それがゼロでない場合、他の誰かがあなたがリリースしたばかりのRCWのほかに、あなたの基礎となるCOMオブジェクトへのCOM参照を保持しています。

+0

私は限り、あなたはあなたが扱わすべてを閉鎖し、問題はそれが行くんexcelapp.Quitを確認してくださいとして発見 - 私は私が見つけたいくつかの既成exporttoexcelコードでいくつかの問題を発見しましたが、また、最後にexcelapp = nullに設定の上、この – BugFinder

+0

GCがCOMコンポーネントを解放しないことを確認しました。明示的に行う必要があります。 – Enigmativity

+1

@Enigmativity GCは、いくつかのAPIを経由して得られた純粋なCOMオブジェクトを解放しませんが、ランタイム呼び出し可能ラッパーを介して取得したCOMオブジェクトを解放しません。エクセルの場合、それは大丈夫です。 –

関連する問題