1

I am trying to close an excel file named TestReport.xlsx using the below code. It is working when only one excel process is running but when I have multiple excel windows open, the MainWindowTitle changes and the code is not killing the desired excel process.

Process[] plist = Process.GetProcessesByName("Excel",".");
foreach(Process p in plist)
{         

    if (p.MainWindowTitle.Contains("TestReport.xlsx") && p.ProcessName == "EXCEL")
    {
        p.Kill();
    }
}
Ash1994
  • 247
  • 1
  • 5
  • 16
  • Have you considered talking to Excel using the COM objects, that way you can close individual workbooks that are open and inspect their names, instead of just killing the process. – Lasse V. Karlsen Jul 18 '15 at 16:12
  • @LasseV.Karlsen Can you do that if your process did not launch Excel via the COM interop? I thought the COM interop could only control instances you create with it. – Scott Chamberlain Jul 18 '15 at 16:15
  • Been a while since I did this but I'm pretty sure you can connect to a running copy of Excel/Word/etc. – Lasse V. Karlsen Jul 18 '15 at 16:17
  • @LasseV.Karlsen Decided to do some research, [turns out you can](http://blogs.msdn.com/b/andreww/archive/2008/11/30/starting-or-connecting-to-office-apps.aspx). With multiple windows open you would want to do the `AccessibleObjectFromWindow` method, cool! – Scott Chamberlain Jul 18 '15 at 16:19

1 Answers1

0

The explanation you are giving in your question is not accurate enough. You must distinguish two cases:

Case 1: You have more than one Excel process each with one workbook. That means that e.g. all your excel workbooks each run in an own hosting excel window. You achieve this when e.g right-clicking on the excel icon, getting an empty excel workbook and loading the workbook you want into that process. In this case your approach works, as every excel process has its own title naming the workbook file name. The requested process is killed when iterating through the excel processes.

Case 2, which is the more "normal" case when working with excel, and to which you probably refer to: You have one excel process hosting more than one workbook, each possibly with several worksheets. In that case Excel acts as you describe and changes its window title (Multiple document interface).

In case 2, when there is only one single excel process present, you can close the workbook in the following way, using COM Interop:

private void button1_Click(object sender, EventArgs e)
{
    CloseExcelWorkbook("TestReport.xlsx");
}

//put the following abbreviation to the "using" block: using Excel = Microsoft.Office.Interop.Excel;
internal void CloseExcelWorkbook(string workbookName)
{
    try 
    {           
        Process[] plist = Process.GetProcessesByName("Excel", ".");
        if (plist.Length  > 1)
            throw new Exception("More than one Excel process running.");
        else if (plist.Length == 0)
             throw new Exception("No Excel process running.");

        Object obj = Marshal.GetActiveObject("Excel.Application");

        Excel.Application excelAppl = (Excel.Application)obj;

        Excel.Workbooks workbooks = excelAppl.Workbooks;
        foreach (Excel.Workbook wkbk in workbooks )
        {
            if (wkbk.Name == workbookName)
                wkbk.Close();
        }
        //dispose
        //workbooks.Close(); //this would close all workbooks
        GC.Collect();
        GC.WaitForPendingFinalizers();
        if (workbooks != null)
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbooks);
        //excelAppl.Quit(); //would close the excel application
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelAppl);
        GC.Collect();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

This approach works in case you have only ONE Excel process running. When there are more than one present, the situation is more complicated as you must get access to all Excel processes. For a discussion for that case, see here.

Another point to observe is to release excel objects properly to avoid stale excel objects. See there.

If you omit the "dispose" activities, it may happen that on closing Excel and continuing to run your app the Excel process runs silently on, as an inspection in Task Manager shows.

Community
  • 1
  • 1
josh
  • 671
  • 5
  • 10