C#.net Excel Interop离开Excel进程挂起

我们在我们的代码中的许多地方使用Excel互操作,但是我有一个似乎并没有closures它所使用的Excel过程的函数..我已经简化了代码,它似乎只要我打开工作簿在这个function,它保持悬挂。 我已经包含了下面的代码,我已经确定每个对象都被定义,释放和清零,但是Excel仍然在运行。

System.Data.DataTable dtExcelSheet = new System.Data.DataTable(); Microsoft.Office.Interop.Excel.Application excelObject = new Microsoft.Office.Interop.Excel.Application(); dtExcelSheet.Columns.Add("SheetName", typeof(string)); dtExcelSheet.Columns["SheetName"].ReadOnly = false; dtExcelSheet.Columns["SheetName"].Caption = "Sheet Name"; Workbooks wbs = excelObject.Workbooks; Workbook excelWorkbook = wbs.Add(excelFile); excelWorkbook.Close(false, System.Reflection.Missing.Value, System.Reflection.Missing.Value); wbs.Close(); excelObject.Quit(); int i1 = Marshal.FinalReleaseComObject(excelWorkbook); int i2 = Marshal.FinalReleaseComObject(wbs); int i3 = Marshal.FinalReleaseComObject(excelObject); excelWorkbook = null; wbs = null; excelObject = null; GC.GetTotalMemory(false); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.GetTotalMemory(true); 

确保你没有在后台线程上调用Excel。 我有一个类似的问题,我正在清理所有的COM对象,但Excel仍然没有死亡,原来是这个问题。

我在这里写下了我的经验和解决scheme。

完整的猜测,但这一行:

 dtExcelSheet.Columns.Add("SheetName", typeof(string)); 

返回创build的列?

如果是这样的话,你可能需要存储这个引用,并在最后清理它。

编辑:另外,我不认为你应该设置variables为null在最后,我认为只是再次访问它们。

你不应该告诉GC收集等,但我认为这可能是你的testing代码。

我已经用这个东西去了一段时间了,所以没有任何东西会跳出来。

在这些情况下,我通常build议将你的excel应用程序对象设置为Visible = true ,看看是否没有popup对话框。 如果他们认为无论你做什么,都会打开一个模式对话框,Excel / Word有时会拒绝closures。 无论如何,这是首先要检查的东西。

我试着运行你的代码,但是我不能重现这个问题。 如果我用一个debugging器遍历它,Excel进程在最后一次调用FinalReleaseComObject之后终止。 罪魁祸首可能在于某些代码不在您的列表中?

当使用COM互操作时,我发现以非常微妙的方式增加COM对象的引用计数是非常容易的。 例如,让我们说你做这样的事情:

 excelWorkbook.Foo.Bar(); 

这可以增加Foo对象上的引用计数,让你无法在之后释放它…并且让Excel进程一直逗留,直到closures应用程序为止。 你可以像这样重新编写上面这行代码:

 Foo foo = excelWorkbook.Foo; foo.Bar(); Marshal.ReleaseComObject(foo); 

它不是很漂亮,但是在完成使用后它会减lessFoo对象的引用计数。

那天同样的事情发生在我身上。 看到我的问题在Excel自动化至修复(问题主要处理多行删除,但我也有同样的问题,因为你知道它必须正确地发布所有的COM对象)。