2010-06-22 66 views
1

我们在我们的代码中的许多地方使用Excel互操作,但是我有一个函数似乎并没有关闭它使用的Excel过程..我简化了代码下来,它似乎只要我在这个功能打开一个工作簿,它保持四处闲逛。我已经包含了下面的代码,我确保每个对象都被定义,发布和清零,但Excel仍在运行。C#.net Excel Interop离开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);  

回答

1

请确保您没有在后台线程上调用Excel。我有一个类似的问题,我正在清理所有的COM对象,但Excel仍然没有死去,结果是问题所在。

我写下了我的经验和解决方案here

1

完整的猜测,但确实该行:

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

返回所创建的列?

如果是这样的话,您可能需要存储该参考文件并在最后清理该参考文件。

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

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

+0

匿名专栏也是我的猜测。 – Mathias 2010-06-23 05:21:10

+0

这是一个数据表中的列,没有连接到Excel表格.... – 2010-06-25 13:27:07

+0

@瑞克:你说的对,我误解了。我的答案剩下的唯一一件事就是在最后不要将它们设置为null,尽管这听起来毫无意义,但值得尝试。 – 2010-06-25 14:23:49

1

这段时间以来我一直在讨论这个问题,所以没有什么会跳出来。

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

+1

如果发生这种情况,您只需设置DisplayAlerts = false即可 – Jess 2010-06-22 21:17:07

1

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

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

excelWorkbook.Foo.Bar(); 

这可以递增Foo对象的引用计数,让你与它释放之后......并留下Excel进程徘徊在你之前没有办法关闭你的应用程序。您可以重新编写代码这样上面的一行:

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

这并不漂亮,但它会递减Foo对象的引用计数,你正在使用它完成之后。

0

前几天发生了同样的事情。在Excel Automation上看到我的问题,关于修复(问题主要涉及多行删除,但我也遇到同样的问题,因为它与正确释放所有COM对象有关)。