Killing an interop Application process

I have the following in a program (written in VB.NET):

Imports Microsoft.Office.Interop.Excel

Public Class Form1
    Dim eApp As New Excel.Application
    Dim w As Excel.Workbook
    w = eApp.Workbooks.Open( "path.xls", ReadOnly:=True)
    .. Processing Code ..
    //Attempts at killing the excel application
    w.Close()
    eApp.Workbooks.Close()
    eApp.Quit()
End Class

When I run this a couple of times, I get a bunch of EXCEL.EXE instances in my task manager. How can I kill these processes in code? All of the ones in the code have been tried and did not work.

Answers


I had to do this a while back in NET 1.1, so please forgive the rust.

On the eApp, there was a Hwind (a win32 window handle - http://msdn.microsoft.com/en-us/library/bb255823.aspx ) or similar object. I had to use that and a pInvoke (http://www.pinvoke.net/default.aspx/user32.GetWindowThreadProcessId ) to get the process id. With that I was able to do a Process.Kill() on the exe.

There maybe a better way to do it now, but this should work.


loop the below line of code until the result is zero or less

System.Runtime.InteropServices.Marshal.ReleaseComObject(eApp)

or check out this link


In order to make Excel exit you need to call Application.Quit, and use one of the following techniques.

  • Call Marshal.ReleaseComObject on every Excel object you instantiate. There's a KnowledgeBase article that describes how to do it. For example in your sample code "eApp.Workbooks.Open" instantiates a Workbooks object without assigning a variable to it. You need to assign a variable as described in the KB article so you can subsequently release it. The catch is that with anything but the simplest automation scenarios it is very difficult to be sure you always release all such objects in all code paths (e.g. by using try/finally to ensure they are released when an exception is thrown).

  • Call GC.Collect and GC.WaitForPendingFinalizers after you release the last Excel object. Some people have suggested that you may need to do this twice.


Start Excel:

Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = xlApp.Workbooks.Open(...);
Worksheet ws = (Worksheet)wb.Worksheets[1];

Kill Excel:

System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
wb = null;
ws = null;

uint idProcess;
GetWindowThreadProcessId((IntPtr)xlApp.Hwnd, out idProcess);

xlApp.DisplayAlerts = false;
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
xlApp = null;
xlApp = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();

Process processo = null;
try
{                   
    processo = Process.GetProcessById((int)idProcess);
}
catch { }

if (processo != null)
    processo.Kill();

I posted a solution to this a few days ago: Killing Excel.EXE on server

Same method as StingyJack mentions; the only one I know to really work.


Use the Using block

Using eApp As New Excel.Application
  Using w As Excel.Workbook
    w = eApp.Workbooks.Open( "path.xls", ReadOnly:=True)
    .. Processing Code ..
    //Attempts at killing the excel application
    w.Close()
    eApp.Workbooks.Close()
    eApp.Quit()
  End Using
End Using

Similar to try/finally block with a disposal in the finally, this will automatically dispose the Excel.Application and Excel.Workbook.

As mentioned in other post, System.Runtime.InteropServices.Marshal.ReleaseComObject(eApp) might also be necessary????


After ExcelApplication.Quit() add the following code.

It will kill the excel application from process.

            Process[] Proc = Process.GetProcessesByName("Excel");
            foreach (Process p in Proc)
            {
                if (p.MainWindowTitle == "")
                    p.Kill();
            }

Tagore Peethala solution is straight forward and works. Basically make sure to WorkBook.CLOSE.. then ExcelApplication.QUIT... then just look for an instance of excel running with nothing open and close it.

myExcelWorksheet = null;
if (myExcelWorkbook != null)
                {
                    myExcelWorkbook.Close();
                    myExcelWorkbook = null;
                }
                if (myExcelApp != null)
                {
                    myExcelApp.Quit();
                    myExcelApp = null;
                }
                foreach (System.Diagnostics.Process myProcess in System.Diagnostics.Process.GetProcessesByName("Excel"))
                {
                    if (myProcess.MainWindowTitle == "")
                    {
                        myProcess.Kill();
                    }
                }

//Quit Excel application
eApp.Quit();

//Release COM objects (every object you used in eApp,like workbooks, Workbook, Sheets, Worksheet)
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;

// Force garbage collector cleaning
GC.Collect();

Need Your Help

Issue loading multiple "internal" links using "Telerik RadPane"

javascript asp.net browser telerik radpanelbar

I have an application where I have put some number of "RadPane" controls and have set the "ContentUrl" to some "internal" pages. The problem here is that they are getting loaded one after the other...

How To show icons in Overflow menu in ActionBar

android actionbarsherlock android-actionbar android-menu

I know it's not possible using the native API. Is there a workaround to implement that kind of view?