Excel进程仍然在后台运行

我正在使用互操作库从excel文件中读取一些数据。 我通过使用Microsoft.Office.Interop.Excel然后读取工作表中的所有数据来获取数据。

 Application ExcelApp = new Excel.Application(); Workbook excelWorkbook = ExcelApp2.Workbooks.Open(excelFileNamePath); _Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName]; Range excelRange = excelWorksheet.UsedRange; //...for loops for reading data ExcelApp.Quit(); 

但是,我的应用程序终止后,我试图编辑我的Excel文件,并打开时有一些问题。 显然,即使我打电话给ExcelApp.Quit() ,excel进程仍然在后台运行。 有没有办法正确closures应用程序使用的Excel文件? 我是新来的C#所以我可能在这里失去了一些东西。

编辑:解决! 显然有一个com的对象不鼓励使用2点的规则 。

 Excel.Application ExcelApp2 = new Excel.Application(); Excel.Workbooks excelWorkbooks = ExcelApp2.Workbooks; Excel.Workbook excelWorkbook = excelWorkbooks.Open(excelFileName); Excel._Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName]; //... excelWorkbook.Close(); Marshal.ReleaseComObject(excelWorkbook); Marshal.ReleaseComObject(excelWorksheet); Marshal.ReleaseComObject(excelRange); ExcelApp2.Quit(); 

还有一个类似的问题 – 答案( https://stackoverflow.com/a/17367570/3063884 ),其中的解决scheme是避免使用双点符号。 相反,为每个对象定义variables,并在每个对象上单独使用Marshal.ReleaseComObject

直接从链接的解决scheme复制:

 var workbook = excel.Workbooks.Open(/*params*/) 

—>而是使用 – >

 var workbooks = excel.Workbooks; var workbook = workbooks.Open(/*params*/) 

然后,完成后,释放每个COM对象:

 Marshal.ReleaseComObject(workbook); Marshal.ReleaseComObject(workbooks); Marshal.ReleaseComObject(excel); 

你没有closures你的工作簿。 closures它,然后在退出Excel应用程序之前释放它:

 excelWorkbook.close(); Marshal.ReleaseComObject(excelWorkbook); ExcelApp.Quit(); 

很长一段时间没有答案,但是对我而言,是调用GC.Collect(); 来自主叫方,

即,而不是

 main() { ... doexcelstuff(); ... } void doexcelstuff() { Excel.Application ExApp2 = new Excel.Application(); Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName); Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName]; //... excelWb.Close(); ExApp2.Quit(); Marshal.ReleaseComObject(excelWb); Marshal.ReleaseComObject(excelWorksheet); Marshal.ReleaseComObject(ExApp2); excelWb = null; excelWorksheet= null; ExApp2= null; GC.Collect(); } 

使用上面的Excel不会死

而是一个非常小的变化,从GC调用的地方

 main() { ... doexcelstuff(); GC.Collect(); // <<-- moved the GC to here (the caller) ... } void doexcelstuff() { Excel.Application ExApp2 = new Excel.Application(); Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName); Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName]; //... excelWb.Close(); ExApp2.Quit(); Marshal.ReleaseComObject(excelWb); Marshal.ReleaseComObject(excelWorksheet); Marshal.ReleaseComObject(ExApp2); excelWb = null; excelWorksheet= null; ExApp2= null; // removed the GC from here } 

我的猜测是垃圾收集器也需要静静地清理堆内部创build的临时值(包括参考/指针) – 其中一些我猜在这种情况下是指向COM对象。

(只需要理解机器如何在源代码下工作)。

互操作是臭名昭着的越野车…保存我的工作簿后,我使用下面的方法,并不再有Excel保持打开时退出我的应用程序的问题:

 while (Marshal.ReleaseComObject(wb) > 0); while (Marshal.ReleaseComObject(xl) > 0); wb = null; xl = null; GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); 

wb是我的工作簿对象,而xl是我的Excel.Application对象。