2012-02-13 7 views
5

Sé que esto se ha discutido anteriormente, pero no pude encontrar una respuesta satisfactoria.Release COM Object en C#

Tengo un archivo de correo electrónico (.msg) que abro como a continuación y luego llamo a Display.

oApp = new Microsoft.Office.Interop.Outlook.Application(); 
mail = (Microsoft.Office.Interop.Outlook.MailItem)oApp.Session.OpenSharedItem(fileName); 
mail.Display(false); 
oApp = null; // do I need to release this object ? 

los usuarios pueden cerrarlo y volver a abrirlo. Antes de que hagan clic en "volver a abrir", verifico si la ventana todavía existe, en caso afirmativo, simplemente envíe un SetForeground (hwnd) a esa ventana. si no, eso significa que el usuario lo cerró, simplemente libere el objeto mailItem y ábralo nuevamente.

public static void ReleaseCOMObject(Microsoft.Office.Interop.Outlook.MailItem item) { 
     int r = System.Runtime.InteropServices.Marshal.ReleaseComObject(item); 
     while (r != 0) { 
      r = System.Runtime.InteropServices.Marshal.ReleaseComObject(item); 
     } 
    } 

Si intento abrir el mismo archivo nuevamente. "A veces" arroja una "excepción de archivo en uso" Entonces, creo que a pesar de que estoy lanzando el MailItem ... no se ha lanzado correctamente.

Qué puedo hacer para asegurar que se libere correctamente. cerrar y volver a abrir un archivo es un escenario muy común.

Cualquier apuntador será de gran ayuda.

+1

Solo debe "liberar" cuando incrementa el contador de referencia, "liberar" referencias de otras personas puede causar problemas. – Matthew

Respuesta

6

Si está utilizando las funciones COM-interop de .NET (usted), entonces no debería tener que preocuparse por esto.

Cuenta de referencia de pistas COM - y cuando el recuento de ref llega a 0 objetos COM se liberan automáticamente - .NET se encarga de trabajar con el mecanismo de recuento de referencias COM estándar para usted.

Si eras P/Invocando en una biblioteca C, las cosas podrían ser diferentes, pero no deberías tener preocupaciones en un escenario estándar como el tuyo.

+0

No estoy seguro de lo que estoy haciendo mal. Observé que una vez que obtengo la "Excepción de uso de archivo", reiniciar mi perspectiva es suficiente. ¿Qué tipo de limpieza necesito para "oApp = new Microsoft.Office.Interop.Outlook.Application();" ? – karephul

+2

Está funcionando ahora -> Hubo otro módulo que se aferraba al MailItem y no lo liberaba. – karephul

+0

Por cierto, solo quería hacerle saber que todavía tenía que "ReleaseCOMObject" para hacerlo funcionar. – karephul

3

haciendo cosas como esta:

mail = (Microsoft.Office.Interop.Outlook.MailItem)oApp.Session.OpenSharedItem(fileName); 

hará que las referencias a la falta de su cesión, incluso cuando se llama ReleaseComObject porque la referencia al objeto hijo no se ha dispuesto de manera adecuada.

Debe hacer las llamadas como esta:

session = oApp.Session; 
mail = (Microsoft.Office.Interop.Outlook.MailItem)session.OpenSharedItem(fileName); 

Y usted debe disponer de cada uno de estos sub-objetos, al igual que la sesión, a su vez.

+0

Noté que si Outlook no se ejecuta en mi máquina ... cerrando y volviendo a abrir (la forma que describí antes) funciona bien. Creo que de alguna manera Outlook mantiene la referencia a ese archivo. ¿Alguna sugerencia allí? Traté de liberar también el objeto Session por separado (no funciona) – karephul

+0

¿Llamas al Marshal?Método ReleaseComObject en el mismo método donde está recibiendo el elemento de correo o lo está haciendo en algún controlador de eventos onclose o algo así? – Nanhydrin

+0

Antes de que el usuario pueda abrir un elemento de correo, verificamos si hay una ventana con el mismo título. Si no, entonces ReleaseComObject (mailItem) .. y abrir de nuevo. [El usuario podría haber cerrado la ventana del correo electrónico] .. Básicamente, retengo el MailItem tanto como puedo para poder guardarlo periódicamente. – karephul