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

时间:2013-12-26 20:32:01

标签: c# wpf excel singleton excel-interop

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

为什么不将一个Excel应用程序实例作为单独的应用程序打开?当我的应用程序关闭时退出这个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));
        }
    }

修改 它似乎工作得很好而且速度更快,但它肯定不是最好的做法。似乎无法找到我的特定excel实例,例如应用程序崩溃后我最终可以用这个片段杀死所有隐藏的excel。

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

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

2 个答案:

答案 0 :(得分:1)

如果你真的需要Excel在后台运行(而不是使用某些第三方库生成Excel文件),那么如果你尝试使用Excel作为单例,那么除了危险之外什么都没有 - 特别是如果你试图使用它通过多个线程。

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

COM object excel interop clean up

Editing an Excel document with Macros in ASP.net

通常,启动Excel,执行您需要执行的任何操作然后立即关闭它会更加清晰。这样可以清理所有资源,下一次启动时会以干净的方式开始。

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

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

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

Writing to excel using OleDb

答案 1 :(得分:0)

作为单例挂在Excel对象上是一个坏主意。用户可以随时关闭Excel,然后您将不再拥有实例(除非您始终隐藏已创建的Excel窗口)。

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

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