I have a windows service that opens up an Excel spreadsheet via the Microsoft.Office.Interop.Excel.Application object.
Application xlApp = new Application();
Workbook workbook = xlApp.Workbooks.Open(fileName, 2, false);
...
...
workbook.Close();
xlApp.Quit();
I would like to kill the EXCEL.exe process that is left running after it is done working with the workbook.
I've tried the following with no success...
// This returns a processId of 0
IntPtr processId;
GetWindowThreadProcessId(new IntPtr(xlApp.Hwnd), out processId);
Process p = Process.GetProcessById(processId.ToInt32());
p.Kill();
Anyone have any ideas as to how I can do this via a Windows Service?
After much reading and frustration I've found a solution!
All credit goes to dotNetkow, nightcoder and Mike Rosenblum for their solutions on this post: How do I properly clean up Excel interop objects?
Here is what I did...
1. Changed build mode of the project to "Release" (in DEBUG mode, COM objects have a hard time disposing of their references.
2. Removed all double dot expressions (all COM objects should be tied to a variable so they can be released)
3. Calling GC.Collect(), GC.WaitForPendingFinalizers(), and Marshal.FinalReleaseComObject() explicitly in a finally block
Here is the acutal code I am using:
Application xlApp = null;
Workbooks workbooks = null;
Workbook workbook = null;
Worksheet sheet = null;
Range r = null;
object obj = null;
try
{
xlApp = new Application();
xlApp.DisplayAlerts = false;
xlApp.AskToUpdateLinks = false;
workbooks = xlApp.Workbooks;
workbook = workbooks.Open(fileName, 2, false);
sheet = workbook.Worksheets[1];
r = sheet.get_Range("F19");
obj = r.get_Value(XlRangeValueDataType.xlRangeValueDefault);
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
if (value != null) Marshal.FinalReleaseComObject(value);
if (r != null) Marshal.FinalReleaseComObject(r);
if (sheet != null) Marshal.FinalReleaseComObject(sheet);
if (workbooks != null) Marshal.FinalReleaseComObject(workbooks);
if (workbook != null)
{
workbook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(workbook);
}
if (xlApp != null)
{
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
}
}