2009-12-15 12 views
7

Des idées pour lesquelles le code suivant ne quitte pas le processus Outlook 2007 créé via COM interop?C# Outlook 2007 L'application COM Interop ne quitte pas!

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 extrait presque identique à l'aide fonctionne Word, donc je me demande si je suis oublier de nettoyer quelque chose ...

Répondre

10

Vous avez un 3ème objet COM référencé dans votre code: app.Session. Cela doit également être libéré correctement. Essayez ce code:

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

Cela a fonctionné. La session est un objet NameSpace. Merci :) – Nikolaos

+0

Pas de problème. J'ai remplacé ce nom de classe dans le code. –

0

Essayez après app.Quit();

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

Toujours continué là ... Merci quand même. – Nikolaos

+2

Mauvais chemin. Collect() doit être le premier. –

+0

@nobugz: Même résultat. Processus toujours là après Quitter(). – Nikolaos

0

Essayez plutôt, ça marche pour moi, il y aura quelques secondes avant que ça se passe:

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

Je ne connais pas les détails de l'Office COM INTEROPS, mais voici un code suggéré d'un MSDN article. Il suggère que la double collecte/attente et l'effacement des pointeurs aide au nettoyage de l'enveloppe RCW.

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

Cette url mais suggère également

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

que je personnellement conseille fortement contre si vous pouvez l'aider, comme vous avez fondamentalement juste que RCW détruit pour votre AppDomain (comme l'article souligne).

[Edit: De plus, le garbage collector .Net se comporte très différemment quand dans un débogueur vs code de déblocage, afin de tester ce en dehors du débogueur est très important]

+2

+1 pour une suggestion de collecte double et un avertissement de débogage. – Nikolaos