11

I have the following code:

private bool IsMousetrapFile(string path)
    {

        logger.Log(validateFileMessage + path);

        Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
        Excel.Workbooks workbooks = xlApp.Workbooks;
        Excel.Workbook xlWorkBook = workbooks.Open(path, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
        Excel.Sheets worksheets = (Excel.Sheets)xlWorkBook.Worksheets;
        Excel.Worksheet ws = null;


        foreach (string sheet in expectedWorksheets)
        {

            try
            {

                ws = (Excel.Worksheet)worksheets.get_Item(sheet);
                logger.Log(validMousetrapFileMessage + path);
            }
            catch
            {
                logger.Log(validateSheetError + sheet + ": " + path);
                if (ws != null)
                    Marshal.ReleaseComObject(ws);
                Marshal.ReleaseComObject(worksheets);
                Marshal.ReleaseComObject(xlWorkBook);
                Marshal.ReleaseComObject(workbooks);
                Marshal.ReleaseComObject(xlApp);

                return false;

            }

        }

        if (ws != null)
            Marshal.ReleaseComObject(ws);
        Marshal.ReleaseComObject(worksheets);
        Marshal.ReleaseComObject(xlWorkBook);
        Marshal.ReleaseComObject(workbooks);
        Marshal.ReleaseComObject(xlApp);

        return true;


    }

Effectively, it checks if an Excel workbook contains specific sheets. Irrespective of whether there is or isn't, I want to Excel processes to end. However, each time a new workbook is open, a new process is added, and never deleted?

PS. I know there is duplicate code there....it shall be tidied soon :)

Darren Young
  • 10,972
  • 36
  • 91
  • 150
  • 2
    Here's the dupe like you asked: http://stackoverflow.com/questions/5357244/quitting-excel-with-c-while-using-excel-automation – gideon Apr 01 '11 at 12:37
  • see the link for more details answers on when excel still runs when you call quit. – gideon Apr 01 '11 at 12:38

3 Answers3

10

Use Excel.Application.Quit() when you are done with processing or whatever you are doing.

In your case: xlApp.Quit();

UPDATE:

@Lasse V. Karlsen pointed out what to do if Excel was already running. Well, here is one solution: ( i did not test the code, this is just to give you an idea )

private void TestMethod()
{
   bool excelWasRunning = System.Diagnostics.Process.GetProcessesByName("excel").Length > 0;

   // your code

   if (!excelWasRunning)
   { 
       xlApp.Quit();
   }
}
Community
  • 1
  • 1
HABJAN
  • 9,212
  • 3
  • 35
  • 59
  • Perfect - thanks. I had tried that, but after the releasing comobjects, and of course it threw an exception. Using it prior to the release work a charm. – Darren Young Apr 01 '11 at 12:34
  • That is of course very rude to do if the user opened up Excel and then started the application... – Lasse V. Karlsen Apr 01 '11 at 12:41
  • @Lasse V. Karlsen: He can check if there is already any running excel with this line of code when he enters his method: System.Diagnostics.Process.GetProcessesByName("excel").Length > 0, and then on method exit he can choose not to call Quit. – HABJAN Apr 01 '11 at 12:49
3

My solution

[DllImport("user32.dll")]
static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);

private void GenerateExcel()
{
    var excel = new Microsoft.Office.Interop.Excel.Application();
    int id;
    // Find the Process Id
    GetWindowThreadProcessId(excel.Hwnd, out id);
    Process excelProcess = Process.GetProcessById(id);

try
            {
                // Your code
}
finally
{
    excel.Quit();

    // Kill him !
    excelProcess.Kill();
}
Tarec
  • 3,268
  • 4
  • 30
  • 47
Loart
  • 71
  • 3
1

Few days back I have implemented Export/Import. I got below code from somewhere when I have searched on Google and it works fine.

ExportToExcel()
{
    try
    {
        //your code
    }
   catch (Exception ex)
        {

        }
        finally
        {
            TryQuitExcel(Application_object);
        }
}
private static void TryQuitExcel(Microsoft.Office.Interop.Excel.Application  application)
        {
            try
            {
                if (application != null &&
                  application.Workbooks != null &&
                  application.Workbooks.Count < 2)
                {
                    application.DisplayAlerts = false;
                    application.Quit();
                    Kill(application.Hwnd);
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(application);
                    application = null;
                }
            }
            catch
            {
                /// Excel may have been closed via Windows Task Manager.
                /// Skip the close.
            }
        }


 private static void Kill(int hwnd)
    {
        int excelPID = 0;
        int handle = hwnd;
        GetWindowThreadProcessId(handle, ref excelPID);

        Process process = null;
        try
        {
            process = Process.GetProcessById(excelPID);

            //
            // If we found a matching Excel proceess with no main window
            // associated main window, kill it.
            //
            if (process != null)
            {
                if (process.ProcessName.ToUpper() == "EXCEL" && !process.HasExited)
                    process.Kill();
            }
        }
        catch { }
    }
simplyaarti
  • 253
  • 4
  • 8