WinWord.exe non si chiuderà dopo aver chiamato Word.Documents.Add – Word .NET Interop

Sto entrando nello scenario classico in cui, durante la creazione di oggetti COM di Word in .NET (tramite l’assembly Microsoft.Office.Interop.Word), il processo WinWord non verrà chiuso anche se sto chiudendo e rilasciando correttamente gli oggetti .

L’ho ristretto all’uso del metodo Word.Documents.Add (). Posso lavorare con Word in altri modi senza problemi (aprire documenti, modificare contenuti, ecc.) E WinWord.exe si chiude quando glielo dico. È una volta che utilizzo il metodo Add () (e solo quando aggiungo un modello ) che il processo viene lasciato in esecuzione.

Ecco un semplice esempio che riproduce il problema:

Dim word As New Word.Application() word.Visible = False Dim documents As Word.Documents = word.Documents Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath), NewTemplate:=False, DocumentType:=Word.WdNewDocumentType.wdNewBlankDocument, Visible:=False) '' dispose objects doc.Close() While (Marshal.ReleaseComObject(doc)  0) End While doc = Nothing While (Marshal.ReleaseComObject(documents)  0) End While documents = Nothing word.Quit() While (Marshal.ReleaseComObject(word)  0) End While word = Nothing GC.Collect() 

Come puoi vedere, sto creando e smaltendo gli oggetti correttamente, anche facendo il passo in più per eseguire il loop di Marsha.ReleaseComObject finché non restituisce il codice corretto. Lavorare con gli oggetti Word va bene per altri aspetti, è solo quel fastidioso Documents.Add che mi sta causando dolore. C’è un altro object che viene creato in questo processo di cui ho bisogno per fare riferimento e disporre? C’è un’altra fase di smaltimento che devo seguire? Qualcos’altro? Il tuo aiuto è molto apprezzato 🙂

Update: ho provato GC.Collect alla fine della fase di eliminazione, ma ancora senza fortuna.

Update 2: ho ridotto il problema all’utilizzo di modelli personalizzati. Quando invoco Documents.Add (…), specifico un modello personalizzato per il nuovo documento. Se non lo faccio e invoco invece Add () senza parametri, il problema non si verifica.

(Tutti i miei consigli sono adattati da questa risposta all’interop di Excel).

Ci sono alcune cose importanti qui:

1) Non usare mai 2 punti sulla stessa linea. Considera anche un indicizzatore come un punto

Buona

 Word.Documents d = wordApp.Documents; Word.Document aDoc = d.Open(/*...*/); 

CATTIVO

 Word.Document aDoc = wordApp.Documents.Open(/*...*/); 

2) Rilascia tutti i tuoi suggerimenti.

3) No davvero, torna indietro e rilascia tutti i tuoi suggerimenti, ne hai perso uno da qualche parte (o almeno lo faccio sempre).

Ecco un esempio completo di ciò che FINALMENTE ha funzionato per me su un progetto dopo tanto lamento e stridore di denti:

 object m = Missing.Value; // this must be an object, not a string. if you forget though, // intellisense will remind you object oFilename = @"C:\my sheet.doc"; object readOnly = false; object isVisible = false; Word.Application wordApp = new Word.ApplicationClass(); wordApp.Visible = false; // remember: don't use 2 dots on 1 line Word.Documents d = wordApp.Documents; Word.Document aDoc = d.Open(ref oFilename, ref m, ref readOnly, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref isVisible, ref m, ref m, ref m, ref m); aDoc.Activate(); object findText = "my old value"; object replaceText = "new and improved value"; object oTrue = true; object oFalse = false; object replace = 2; object wrap = 1; Word.Selection s = wordApp.Selection; Word.Find f = s.Find; f.Execute(ref findText, ref oTrue, ref oTrue, ref oFalse, ref oFalse, ref oFalse, ref oTrue, ref wrap, ref oFalse, ref replaceText, ref replace, ref oFalse, ref oFalse, ref oFalse, ref oFalse); aDoc.SaveAs(ref oFilename, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m); object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges; // casting here because intellisense complained of ambiguity (aDoc as Word._Document).Close(ref doNotSaveChanges, ref m, ref m); // release each in the reverse of the order in which it was first used // ReleaseComObject might also work as well. I haven't tested yet Marshal.FinalReleaseComObject(f); Marshal.FinalReleaseComObject(s); Marshal.FinalReleaseComObject(aDoc); Marshal.FinalReleaseComObject(d); // must quit app before releasing // again: casting because intellisense complained of ambiguity (wordApp as Word._Application).Quit(ref m, ref m, ref m); Marshal.FinalReleaseComObject(wordApp); 

Hai provato a cambiare

 oWord.Visible = False 

a

 oWord.Visible = True 

?

Chiedo perché Word potrebbe chiederti di fare qualcosa che è legato a questo modello che stai cercando di usare. Se pensa che ci sia una finestra di dialogo che mostra, normalmente non si spegne. IIRC, c’è un modo per uscire da Espress in modo tale da forzare Esci e non attenderà alcuna finestra di dialogo. Ma è passato un po ‘di tempo.

Ho fatto solo l’automazione di Excel, ma ho incontrato problemi simili. Facendo riferimento ad un vecchio codice, il passaggio finale in chiusura ha la linea GC.Collect ()

Questo articolo lo menziona anche: http://support.microsoft.com/kb/317109

Prova a chiamare GC.WaitForPendingFinalizers() e utilizza Marshal.FinalReleaseComObject anziché Marshal.ReleaseComObject . Questo elimina la necessità di looparlo.

Aggiorna il tuo codice e provalo (le chiamate GC sono all’inizio di proposito):

 GC.Collect() GC.WaitForPendingFinalizers() oDoc.Close() Marshal.FinalReleaseComObject(oDoc) Marshal.FinalReleaseComObject(oDocuments) oWord.Quit() Marshal.FinalReleaseComObject(oWord) 

Si potrebbe anche voler verificare questa domanda correlata discutendo il problema per Excel.

Ho capito che l’uso di Documents.Add () quando si usa un modello personalizzato è la colpa. Non riesco a spiegare perché questo lascerebbe il blocco di WinWord.exe. Tuttavia ci sono altri modi per creare documenti da modelli che non comportano lo stesso problema.

Così ho sostituito:

 Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath)) 

con:

 Dim doc As Word.Document = documents.Add() doc.AttachedTemplate = templatePath doc.UpdateStyles() 

Utilizzare AttachedTemplate per specificare che il modello funziona per me e non lasciare sospeso WinWord.exe.

(Tuttavia è sorto un nuovo problema … Un’immagine nel piè di pagina del modello non viene copiata nel documento quando si utilizza AttachedTemplate / UpdateStyles. Ne parlo come un problema separato, ma poiché questo metodo risolve il mio problema originale, sono soddisfatto Grazie a tutti quelli che hanno offerto risposte!)

Ho avuto lo stesso problema quando lo stavo facendo:

 object missing = System.Reflection.Missing.Value; wordApplication.Quit(ref missing, ref missing, ref missing); 

Ho risolto in questo modo:

 object objFalse = false; wordApplication.Quit(ref objFalse, ref objFalse, ref objFalse); 

Non chiedermi perché, automatizzare l’ufficio è un’avventura 🙂

Mi sono imbattuto nel tuo post a causa di un problema simile con il modello. Avrei ricevuto un messaggio che mi chiedeva di salvare il file .dotm ogni volta che cercavo di chiudere la parola nel mio programma. Non ho potuto utilizzare la risposta accettata perché non ho un percorso di template esatto, ho solo aperto qualsiasi documento ricevuto dal programma.

quello che ho usato è

 Word.NormalTemplate.Saved = true; 

quando ho usato quel codice prima di eliminare l’applicazione, non avrei più visualizzato la finestra di dialogo che diceva che non avevo salvato il modello e che avrebbe eseguito la disposizione senza lasciare il processo ” winWord.exe ” indesiderato in esecuzione.

Ho ricevuto il consiglio “NormalTemplate.Saved” dall’utente ” NeedSomeAnswers ” sui forum di base visivi qui . Nelle sue parole “[it] in realtà non salva in Normal, dice semplicemente a Word che il Normal è già stato salvato quindi non è necessario salvarlo”.

Penso che questa sia una seconda risposta allo stesso problema. Spero possa essere d’aiuto.

Buona giornata e stai bene.

-ogni giorno il tuo codice funziona è una buona giornata per festeggiare-

“oDocuments” ha un metodo .Dispose () o .Close ()? stai eliminando gli altri 2, ma non questo.

Anche se questo è C # ma forse ti aiuterà. Sto usando questo metodo per unire più documenti in uno solo. Trasmetto tutti i documenti in Arraylist e Word sembra chiudersi correttamente quando finisce.

  public static void documentsMerge(object fileName, ArrayList arrayList) { // object fileName = Path.Combine(Environment.CurrentDirectory, @"NewDocument.doc"); File.Delete(fileName.ToString()); try { wordApplication = new ApplicationClass(); var doc = wordApplication.Documents.Add(ref missing, ref missing, ref missing, ref missing); try { doc.Activate(); int count = 0; foreach (var alItem in arrayList) { addDocument(alItem, doc, count == 0); count++; } // addDocument(@"D:\Projects\WordTests\ConsoleApplication1\Documents\Doc1.doc", doc ) ; //, false); // addDocument(@"D:\Projects\WordTests\ConsoleApplication1\Documents\Doc2.doc", doc ) ; //, true); doc.SaveAs(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); } finally { doc.Close(ref missing, ref missing, ref missing); } } finally { wordApplication.Quit(ref missing, ref missing, ref missing); } } 

Il blocco finally è utile per cleaning up eventuali risorse allocate nel blocco try e per eseguire qualsiasi codice che deve essere eseguito anche in presenza di un’eccezione. Il controllo viene sempre passato al blocco finally indipendentemente da come il blocco try si chiude.

Quindi prova a mettere il tuo codice in try / finally e vedi come si comporta allora?

Per VB.NET

 Try ' Statement which can cause an exception. Catch x As Type ' Statements for handling the exception Finally End Try 'Any cleanup code 

Non si deve scartare l’object documento creato in Word.Documents.Add . Salvare e chiamare Marshal.ReleaseComObject su ogni object COM che si ottiene dall’automazione quando si è terminato, ovvero se non si memorizzano nella cache gli oggetti da nessuna parte .

 oWord.Visible = True 

Risolto il problema per me. Il problema di fondo era il recupero dei documenti. Appariva una finestra di dialogo nonostante avesse una linea:

 _wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone; 

Ho usato tutti i trucchi che sono stati mostrati qui ma fino a quando l’elenco di recupero del documento non è stato cancellato, un processo di parola “zombie” è stato lasciato indietro ogni volta che la mia applicazione è stata eseguita.

questa è una soluzione perfetta, ho avuto lo stesso problema, ho appena seguito questo e funziona perfettamente.

object objFalse = falso;

wordApplication.Quit (ref objFalse, ref objFalse, ref objFalse);

Avevo provato ad automatizzare la creazione di un documento in word da vb.net, ma winword.exe era ancora in esecuzione, anche dopo aver chiuso il documento. Mi sono imbattuto in una soluzione a questo problema; Ho spostato la dimensione dell’object parola all’interno della subroutine che stavo usando per modificare il documento, invece di quotarlo indipendentemente da una subroutine (il mio metodo iniziale).

Spero che questo ti aiuti.