2009-12-15 8 views
7

Qualche motivo per cui il seguente codice non esce dal processo di Outlook 2007 creato tramite interoperabilità COM?C# Outlook 2007 L'applicazione di interoperabilità COM non si chiude!

Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application(); 

var item = app.Session.OpenSharedItem("C:\\test.msg") as Microsoft.Office.Interop.Outlook.MailItem; 
string body = item.HTMLBody; 
int att = item.Attachments.Count; 

(item as Microsoft.Office.Interop.Outlook._MailItem).Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard); 
System.Runtime.InteropServices.Marshal.ReleaseComObject(item); 

(app as Microsoft.Office.Interop.Outlook._Application).Quit(); 
System.Runtime.InteropServices.Marshal.ReleaseComObject(app); 
System.Diagnostics.Debugger.Break(); 

Un frammento quasi identico utilizzando Word funziona, quindi mi chiedo se sto dimenticando di ripulire qualcosa ...

risposta

10

si ha un oggetto COM 3 ° si fa riferimento nel codice: app.Session. Anche questo deve essere rilasciato correttamente. Prova di questo codice:

Microsoft.Office.Interop.Outlook.Application app = null; 
Microsoft.Office.Interop.Outlook.NameSpace session = null; 
Microsoft.Office.Interop.Outlook.MailItem item = null; 

try { 
    app = new Microsoft.Office.Interop.Outlook.Application(); 
    session = app.Session; 
    item = session.OpenSharedItem("C:\\test.msg") as Microsoft.Office.Interop.Outlook.MailItem; 

    string body = item.HTMLBody; 
    int att = item.Attachments.Count; 

    (item as Microsoft.Office.Interop.Outlook._MailItem).Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard); 

    (app as Microsoft.Office.Interop.Outlook._Application).Quit(); 
} finally { 
    if(item != null) { 
     System.Runtime.InteropServices.Marshal.FinalReleaseComObject(item); 
    } 
    if(session != null) { 
     System.Runtime.InteropServices.Marshal.FinalReleaseComObject(session); 
    } 
    if(app != null) { 
     System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app); 
    } 
} 
+0

Ha funzionato. La Sessione è un oggetto NameSpace. Grazie :) – Nikolaos

+0

Nessun problema. Ho sostituito quel nome di classe nel codice. –

0

Prova a seguire dopo app.Quit();

// ReleaseComObject(xApp); 
GC.WaitForPendingFinalizers(); 
GC.Collect(); 
+0

ancora persistente là ... Grazie comunque. – Nikolaos

+2

Modo sbagliato. Collect() deve essere il primo. –

+0

@nobugz: stesso risultato. Processo ancora lì dopo Quit(). – Nikolaos

0

Prova a modificare, per me funziona, ci sarà un ritardo di pochi secondi prima che va:

app.Quit(); // 
System.Runtime.InteropServices.Marshal.ReleaseComObject(app); 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
2

non so le specifiche dei COM Interops di Office, ma ecco qualche codice suggerito da un MSDN article. Suggerisce la doppia raccolta/attesa e la cancellazione dei puntatori aiuta con la pulitura del wrapper RCW.

item = null; 
app.Quit(); 
app = null; 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 

tale URL però suggerisce anche

while (Marshal.ReleaseComObject(app) > 0) { } 

che io personalmente vivamente sconsigliato se si può farne a meno, come hai fondamentalmente solo distrutto che RCW per l'AppDomain (come l'articolo fa notare).

[Edit: Inoltre la spazzatura collettore Net comporta molto diverso quando all'interno di un debugger vs codice di rilascio, in modo da prove all'esterno del debugger è molto importante]

+2

+1 per avviso doppio suggerimento e debugging. – Nikolaos