2009-12-15 8 views
7

Gibt es irgendwelche Ideen, warum der folgende Code den Outlook 2007-Prozess, der über COM-Interop erstellt wurde, nicht beendet?C# Outlook 2007 COM-Interop-Anwendung wird nicht beendet!

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

Ein fast identischer Schnipsel mit Word arbeitet, so frage ich mich, ob ich etwas ...

Antwort

10

Sie haben ein Objekt 3. COM in Ihrem Code verwiesen: app.Session. Dies muss auch korrekt freigegeben werden. Versuchen Sie diesen 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

Das hat funktioniert. Die Sitzung ist ein NameSpace-Objekt. Danke :) – Nikolaos

+0

Kein Problem. Ich habe diesen Klassennamen im Code ersetzt. –

0

Versuchen nach app.quit folgenden aufzuräumen bin zu vergessen();

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

Dennoch gibt verweilenden ... Danke trotzdem. – Nikolaos

+2

Falscher Weg. Collect() muss zuerst sein. –

+0

@nobugz: Gleiches Ergebnis. Prozess immer noch nach Quit(). – Nikolaos

0

dies stattdessen versuchen, es für mich funktioniert, wird es ein paar Sekunden dauern, bis es geht:

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

Ich weiß nicht, die Besonderheiten der Office COM Interops, aber hier ist ein Code aus einem MSDN article vorgeschlagen. Es schlägt vor, dass das doppelte Sammeln/Warten und Löschen der Zeiger bei der RCW-Wrapper-Bereinigung hilft.

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

Das url aber schlägt auch

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

, die würde ich persönlich gegen stark beraten, wenn Sie es vermeiden kann, da man im Grunde, dass RCW nur ​​zerstört haben für Ihre AppDomain (wie der Artikel weist darauf hin,).

[Edit: Auch die .NET Garbage Collector verhält sich ganz anders, wenn sie innerhalb eines Debuggers vs Freigabe-Code, so testet diese außerhalb des Debuggers ist sehr wichtig]

+2

+1 für Doppel sammeln Vorschlag und Debugging-Warnung. – Nikolaos