我们在代码中的许多地方使用Excel互操作,但是我有一个功能似乎永远不会关闭它使用的Excel进程..我已经简化了代码,它似乎只是每当我在这个函数中打开一个工作簿它会一直闲逛。我已经包含了下面的代码,我确保每个对象都已定义,发布和清空,但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);
答案 0 :(得分:1)
确保您没有在后台线程上调用Excel。我有一个类似的问题,我正在清理所有COM对象,但Excel仍然没有死亡,结果证明是问题。
我写了我的经验和解决方案here。
答案 1 :(得分:1)
完全猜测,但这一行:
dtExcelSheet.Columns.Add("SheetName", typeof(string));
返回创建的列?
如果是这样的话,你可能需要存储该引用并在最后清理它。
编辑:另外,我不认为你应该在最后将变量设置为null,我认为只是再次访问它们。
你不应该告诉GC收集等等,但我认为这可能是你的测试代码。
答案 2 :(得分:1)
已经有一段时间了,因为我已经习惯了这些东西,所以什么都没有跳出来。
在这些情况下,我通常的建议是将您的Excel应用程序对象设置为Visible = true
,以查看是否没有弹出对话框。 Excel / Word有时会拒绝关闭,如果他们认为无论你做什么,他们都会打开一个模态对话框。无论如何,这是第一件要检查的事情。
答案 3 :(得分:1)
我尝试运行您的代码,但我无法重现该问题。如果我使用调试器单步调试,Excel进程会在最后一次调用FinalReleaseComObject
后终止。罪魁祸首可能在于您的列表中没有的某些代码吗?
使用COM互操作时,我发现以非常微妙的方式增加COM对象的引用计数太容易了。例如,假设您执行以下操作:
excelWorkbook.Foo.Bar();
这会增加Foo
对象上的引用计数,让您无法在之后释放它...并且让Excel进程一直闲着,直到您关闭应用程序为止。你可以像这样重写上面的代码:
Foo foo = excelWorkbook.Foo;
foo.Bar();
Marshal.ReleaseComObject(foo);
它不是那么漂亮,但是在完成使用后它会减少Foo
对象上的引用计数。
答案 4 :(得分:0)
前几天发生了同样的事情。请参阅我在Excel Automation上关于修复的问题(问题主要涉及多行删除,但我也遇到了与发布它与正确释放所有COM对象有关的问题)。