Excel application singleton - possible threats of using only one Excel app instance without quitting?

StackOverflow https://stackoverflow.com/questions/20790884

Domanda

I am working on a WPF application that uses Excel quite heavily for reporting. It takes too much time to open a new Excel app whenever I need Excel app instance to generate a new report.

Why not to keep one Excel app instance open as a singleton just for my app? And to quit this Excel singleton when my application closes? There is only a small risk that the Excel app instance stays open, I think. Or is there any hidden threat in doing this?

My code:

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

EDIT It seems to be working quite ok and faster, though it is certainly not the very best practice. There seems to be no way to find my particular excel instance e.g. after app crash. I can eventually kill all hidden excels with this snippet.

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

I have observed only one problem: when user tries to open excel file from explorer using file association, it somehow finds and shows my hidden instance and the required file does not appear in Excel. When excel is opened just running excel.exe e.g from desktop shortcut then a new instance is opened and it is ok.

È stato utile?

Soluzione

If you really do need Excel to run in the background (as opposed to generating Excel files using some 3rd-party library), there is nothing but danger if you try to use Excel as a singleton - especially if you try to use it over multiple threads.

Read these answers of mine (to somewhat related questions):

COM object excel interop clean up

Editing an Excel document with Macros in ASP.net

In general, it's much cleaner to start up Excel, perform whatever operation you need it to do and then shut it down immediately. This cleans up all resources and the next startup begins with a clean slate.

I don't know your actual usage pattern of Excel so not all of the details may apply to you but quite a few of them will. I may be able to add more detail if you have more specific questions.

If you just need to read / write .xlsx files, you may be able to use the OpenXML SDK instead of Excel. I haven't used it so I don't know if it'd fit your needs.

Edit: if you're using Excel to generate your data (which is typically very slow), you can look into other approaches where the data is generated as a text file / recordset and then imported into Excel:

Writing to excel using OleDb

Altri suggerimenti

Hanging on the the Excel object as a singleton is a bad idea. The user may close Excel at any time and then you won't have an instance any more (unless you keep the Excel window you have created hidden all the time).

Why don't you grab a running Excel instance if one exists and otherwise create a new one?

  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();
  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top