Duplicar posibles:
How to properly clean up Excel interop objects in C## interoperabilidad C: Proceso de Excel no salir después de añadir nueva hoja de cálculo al archivo existente
He leído muchos de los otros hilos aquí acerca de la gestión de referencias COM mientras utilizando la interoperabilidad .Net-Excel para asegurarnos de que el proceso de Excel sale correctamente al salir, y hasta ahora las técnicas han funcionado muy bien, pero recientemente encontré un problema al agregar nuevas hojas de trabajo a un archivo de libro de trabajo existente.
El siguiente código deja un proceso zombie de Excel.
Si agrego una hoja de trabajo a un archivo de libro recién creado, sale bien. Si ejecuto el código excluyendo la línea .Add()
, sale bien. (El archivo existente del que estoy leyendo es un archivo vacío creado por el código comentado)
¿Alguna idea?
//using Excel = Microsoft.Office.Interop.Excel;
//using System.Runtime.InteropServices;
public static void AddTest()
{
string filename = @"C:\addtest.xls";
object m = Type.Missing;
Excel.Application excelapp = new Excel.Application();
if (excelapp == null) throw new Exception("Can't start Excel");
Excel.Workbooks wbs = excelapp.Workbooks;
//if I create a new file and then add a worksheet,
//it will exit normally (i.e. if you uncomment the next two lines
//and comment out the .Open() line below):
//Excel.Workbook wb = wbs.Add(Excel.XlWBATemplate.xlWBATWorksheet);
//wb.SaveAs(filename, m, m, m, m, m,
// Excel.XlSaveAsAccessMode.xlExclusive,
// m, m, m, m, m);
//but if I open an existing file and add a worksheet,
//it won't exit (leaves zombie excel processes)
Excel.Workbook wb = wbs.Open(filename,
m, m, m, m, m, m,
Excel.XlPlatform.xlWindows,
m, m, m, m, m, m, m);
Excel.Sheets sheets = wb.Worksheets;
//This is the offending line:
Excel.Worksheet wsnew = sheets.Add(m, m, m, m) as Excel.Worksheet;
//N.B. it doesn't help if I try specifying the parameters in Add() above
wb.Save();
wb.Close(m, m, m);
//overkill to do GC so many times, but shows that doesn't fix it
GC();
//cleanup COM references
//changing these all to FinalReleaseComObject doesn't help either
while (Marshal.ReleaseComObject(wsnew) > 0) { }
wsnew = null;
while (Marshal.ReleaseComObject(sheets) > 0) { }
sheets = null;
while (Marshal.ReleaseComObject(wb) > 0) { }
wb = null;
while (Marshal.ReleaseComObject(wbs) > 0) { }
wbs = null;
GC();
excelapp.Quit();
while (Marshal.ReleaseComObject(excelapp) > 0) { }
excelapp = null;
GC();
}
public static void GC()
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
}
Si el método GC no funciona porque todavía está sosteniendo una referencia en alguna parte. ¿Estás seguro de que ese es todo el código relevante? –
Sí, me sale un proceso zombie dejando correr el código anterior exactamente como está escrito – yoyoyoyosef