web-dev-qa-db-ja.com

Microsoft.Office.Interop.Word.Applicationの破棄

(投稿からのフォローの一部(未回答のまま): https://stackoverflow.com/q/6197829/314661

次のコードを使用する

Application app = new Application();
_Document doc = app.Documents.Open("myDocPath.docx", false, false, false);
doc.PrintOut(false);
doc.Close();

プログラムでファイルを開いて印刷しようとしています。

問題は、上記のコードを実行するたびに新しいWINWORD.exeプロセスが開始されることであり、これにより明らかにすべてのメモリがすぐに消費されます。

アプリケーションクラスには、dispose/closeまたは同様のメソッドが含まれていないようです。

少し調査した後、コードを次のように(実現し)変更しました。

 Application app = new Application();
 _Document doc = app.Documents.Open(fullFilePath + ".doc", false, false, false);
 doc.PrintOut(false);
 doc.Close();
 int res = System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
 int res1 = System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

そして、残りの参照カウントはゼロですが、プロセスは残っていますか?

PS:Microsoft.Office.Interopライブラリのバージョン14を使用しています。

37

おそらく_doc = null_を設定してGC.Collect()を呼び出してみてください

編集、実際に自分のコードではなく、私はそれをどこで手に入れたか忘れていますが、これはExcelを処分するために使用するものであり、それはあなたがこれから何かを集めることができるかもしれません:

_public void DisposeExcelInstance()
{
    app.DisplayAlerts = false;
    workBook.Close(null, null, null);
    app.Workbooks.Close();
    app.Quit();
    if (workSheet != null)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet);
    if (workBook != null)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(workBook);
    if (app != null)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
    workSheet = null;
    workBook = null;
    app = null;
    GC.Collect(); // force final cleanup!
}
_
41
Nick

Quitを呼び出す必要はありませんか?

app.Quit();
51
Enigmativity

最良の解決策..最後:

try {

    Microsoft.Office.Interop.Word.Application appWord = new Microsoft.Office.Interop.Word.Application();
    appWord.Visible = false;
    Microsoft.Office.Interop.Word.Document doc = null;
    wordDocument = appWord.Documents.Open((INP), ReadOnly: true);

    wordDocument.ExportAsFixedFormat(OUTP, Microsoft.Office.Interop.Word.WdExportFormat.wdExportFormatPDF);

    // doc.Close(false); // Close the Word Document.
    appWord.Quit(false); // Close Word Application.
} catch (Exception ex) {
    Console.WriteLine(ex.Message + "     " + ex.InnerException);
}
3
T Bass

アプリケーションを閉じるには、app.Quit()を呼び出す必要があります。私は以下のコードを使用しましたが、それは私にとって魅力のように働きました-

try
{
   Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();
   wordApp.Visible = false;
   Microsoft.Office.Interop.Word.Document doc = null;

   //Your code here...

   doc.Close(false); // Close the Word Document.
   wordApp.Quit(false); // Close Word Application.
}
catch (Exception ex)
{
   MessageBox.Show(ex.Message + "     " + ex.InnerException);
}
finally
{
   // Release all Interop objects.
   if (doc != null)
      System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
   if (wordApp != null)
      System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
   doc = null;
   wordApp = null;
   GC.Collect();
}
2
a1ashiish

誰も取り上げていないように思える主な問題は、Wordが既に開いている場合、そもそも新しいApplicationオブジェクトを作成すべきではないということです。 COMやVB6の時代からコーディングを続けてきた私たちは、GetActiveObjectを覚えているでしょう。幸いなことに、.NetにはProgIDのみが必要です。

これを行うための推奨される方法は次のとおりです。

try
{
    wordApp = (Word.Application) Marshal.GetActiveObject("Word.Application");
}
catch(COMException ex) when (ex.HResult == -2147221021)
{
    wordApp = new Word.Application();
}
1
Charlie

これを試して..

doc.Close(false);
app.Quit(false);
if (doc != null)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
if (app != null)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
doc = null;
app = null;
GC.Collect();
1
Asiri Jayaweera

ドキュメントを閉じ、次にアプリケーションを閉じて、それが機能し、ガベージコレクションを強制します。

// Document
object saveOptionsObject = saveDocument ? Word.WdSaveOptions.wdSaveChanges : Word.WdSaveOptions.wdDoNotSaveChanges;
this.WordDocument.Close(ref saveOptionsObject, ref Missing.Value, ref Missing.Value);

// Application
object saveOptionsObject = Word.WdSaveOptions.wdDoNotSaveChanges;
this.WordApplication.Quit(ref saveOptionsObject, ref Missing.Value, ref Missing.Value); 

GC.Collect();
GC.WaitForPendingFinalizers();
0
gangelo