如何检测Excel工作簿是否closures(在C#中使用Interop)?

我正在使用Microsoft.Office.Interop.Excel.Application读取Excel文件中的值的C#项目:

 try { Application xlApp = new Application(); Workbook workbook = xlApp.Workbooks.Open(filename) // ... Load Excel values ... } finally { // ... Tidy up ... } 

finally块中,我想确保一切都被closures并正确处置,所以没有任何东西在内存中挂起,Excelclosures干净。 已经看到了这个代码应该看起来像什么(比我想象的更复杂)的各种线程,但它可能包括的一件事是:

 if (workbook != null) { workbook.Close(); // ... possibly also Marshal.FinalReleaseComObject(workbook); } 

但是,如果工作簿已经closures,这会引发一个错误,所以如何安全地检查这个? 如果可能的话,宁愿不要仅仅捕获错误,因为这种types的东西往往会扭曲debugging。 在closures之前find工作簿状态是否有一个干净的方法?

还有一个问题 – 如果xlApp.Quit();是否需要xlApp.Quit(); 之后完成 – 将退出Excel应用程序导致workbook.Close() (和任何COM对象释放)隐式发生?

在您打开工作簿时,最好的build议是跟踪工作簿并在适当的时候closures工作簿。 如果您的代码非常详细,那么您可以存储一个Boolean值,指示文件当前是打开还是closures。

在Excel中没有属性,如IsOpen。 您可以尝试引用该工作簿:

 Workbook wbTest = xlApp.Workbooks.get_Item("some.xlsx"); 

但是如果这本书没有打开,这会造成一个COM错误,所以会变得相当混乱。

相反,创build自己的函数IsOpen返回一个布尔值,并循环通过当前打开的工作簿( Workbooks集合)检查名称,使用如下代码:

 foreach (_Workbook wb in xlApp.Workbooks) { Console.WriteLine(wb.Name); } 

如果工作簿已保存,则workbook.Close()将不必要,这反映了Excel的正常行为。 但是,所有的Excel对象引用都需要被释放。 正如你所发现的那样,这有点太过分了, CloseQuit自己并没有做到这一点。


  static bool IsOpen(string book) { foreach (_Workbook wb in xlApp.Workbooks) { if (wb.Name.Contains(book)) { return true; } } return false; }