Excel应用程序单例 – 只使用一个Excel应用程序实例而不退出的可能威胁?

我正在使用Excel进行报告的WPF应用程序。 每当我需要Excel应用程序实例生成新报表时,需要花费太多时间来打开新的Excel应用程序。

为什么不保留一个Excel应用程序实例作为一个单例打开只为我的应用程序? 当我的应用程序closures时退出此Excel单身人士? 我认为,Excel应用程序实例保持打开的风险很小。 或者这样做有没有隐藏的威胁?

我的代码:

private static Microsoft.Office.Interop.Excel.Application _ExcelApp = null; public static Microsoft.Office.Interop.Excel.Application ExcelApp { get { return _ExcelApp; } private set { _ExcelApp = value; } } public static void QuitExcel() { if (ExcelReports.ExcelApp != null) { ExcelReports.ExcelApp.Quit(); ExcelReports.ExcelApp = null; } } public static void StartExcel() { try { ExcelReports.ExcelApp = new Microsoft.Office.Interop.Excel.Application(); } catch (System.Runtime.InteropServices.COMException ex) { throw new ApplicationException(String.Format("Cannot start Excel.\n\r{0}", ex.Message)); } } 

编辑它似乎是工作相当好,更快,虽然这当然不是最好的做法。 似乎没有办法find我的特殊的Excel实例,例如应用程序崩溃后。 我最终可以用这个片段杀死所有隐藏的优秀。

  List<Process> procs = new List<Process>(); procs.AddRange(Process.GetProcessesByName("excel")); foreach (Process p in procs) if ((int)p.MainWindowHandle == 0) { //Kill excel 

我只观察到一个问题:当用户试图使用文件关联从资源pipe理器中打开excel文件时,它以某种方式查找并显示我的隐藏实例,并且所需的文件不会出现在Excel中。 当excel打开时,只需运行excel.exe,例如从桌面快捷方式,然后打开一个新的实例,就可以了。

如果你确实需要在后台运行Excel(而不是使用一些第三方库生成Excel文件),那么如果你尝试将Excel作为单例使用,那么就没有什么危险 – 尤其是如果你试图通过多个线程。

阅读我的这些答案(有些相关的问题):

COM对象excel interop清理

使用ASP.net中的macros编辑Excel文档

一般来说,启动Excel,执行任何您需要的操作,然后立即将其closures即可。 这清理了所有资源,下一次启动以一个干净的石板开始。

我不知道你的Excel的实际使用模式,所以并不是所有的细节都可能适用于你,但是其中很多细节都适用。 如果您有更具体的问题,我可以添加更多的细节。

如果您只需要读取/写入.xlsx文件,则可以使用OpenXML SDK而不是Excel。 我没有使用它,所以我不知道它是否适合您的需求。

编辑 :如果您使用Excel生成数据(通常非常慢),则可以查看其他方法,将数据生成为文本文件/logging集,然后导入到Excel中:

使用OleDb写入excel

挂在Excel对象作为一个单身人士是一个坏主意。 用户可以在任何时候closuresExcel,然后您将不再有实例(除非您始终保持隐藏的Excel窗口)。

为什么不抓取运行的Excel实例(如果存在),否则创build一个新实例?

  Excel.Application myExcelApp = null; try { myExcelApp = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application") as Excel.Application; } catch (System.Runtime.InteropServices.COMException e) { // Excel Not Running myExcelApp = new Microsoft.Office.Interop.Excel.Application(); }