web-dev-qa-db-fra.com

Élimination de Microsoft.Office.Interop.Word.Application

(Un peu à la suite de la publication (qui reste sans réponse): https://stackoverflow.com/q/6197829/314661 )

Utilisation du code suivant

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

J'essaie d'ouvrir et d'imprimer un fichier par programme.

Le problème est que chaque fois que j'exécute le code ci-dessus, un nouveau processus WINWORD.exe est démarré et, évidemment, cela consomme rapidement toute la mémoire.

La classe d'application ne semble pas contenir une méthode dispose/close ou similaire.

Après un peu de recherche, j'ai (réalisé) et changé le code comme suit.

 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);

Et je peux voir que le nombre de références restantes est nul mais les processus restent?

PS: j'utilise la version 14 de la bibliothèque Microsoft.Office.Interop.

37
Maxim Gershkovich

Essayez peut-être de définir doc = null Et d'appeler GC.Collect()

Modifier, pas vraiment mon propre code, j'oublie où je l'ai obtenu, mais c'est ce que j'utilise pour disposer d'Excel, et il fait le travail, vous pouvez peut-être en tirer quelque chose:

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

Vous n'avez pas besoin d'appeler Quit?

app.Quit();
51
Enigmativity

La meilleure solution .. dernière:

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

Vous devez appeler app.Quit() pour fermer l'application. J'ai utilisé le code ci-dessous et cela a fonctionné comme un charme pour moi -

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

Je pense que le principal problème, que personne ne semble avoir compris, est que vous ne devriez pas créer un nouvel objet Application en premier lieu si Word est déjà ouvert. Ceux d'entre nous qui codent depuis l'époque de COM et/ou VB6 se souviendront de GetActiveObject. Heureusement .Net ne nécessite qu'un ProgID.

La façon recommandée de procéder est la suivante:

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

Essaye ça..

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

Je ferme le document, puis l'application, qui fonctionne pour moi, puis force la collecte des ordures.

// 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