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(); }