I've seen this approach used a few times, wrap the Excel functionality in a class that implements IDisposable as follows
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Microsoft.Office.Interop.Excel;
namespace ExcelTools
{
internal class ExcelWrapper : IDisposable
{
private class Window
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr ProcessId);
public static IntPtr GetWindowThreadProcessId(IntPtr hWnd)
{
IntPtr processId;
IntPtr returnResult = GetWindowThreadProcessId(hWnd, out processId);
return processId;
}
public static IntPtr FindExcel(string caption)
{
System.IntPtr hWnd = FindWindow("XLMAIN", caption);
return hWnd;
}
}
private Application excel;
private IntPtr windowHandle;
private IntPtr processId;
public ExcelWrapper()
{
excel = CreateExcelApplication();
windowHandle = Window.FindExcel("your instance title");
processId = Window.GetWindowThreadProcessId(windowHandle);
}
private Application CreateExcelApplication()
{
Application excel = new Application();
excel.Caption = "your instance title";
excel.DisplayAlerts = false;
excel.AlertBeforeOverwriting = false;
excel.AskToUpdateLinks = false;
return excel;
}
public Application Excel
{
get { return this.excel; }
}
public int ProcessId
{
get { return this.processId.ToInt32(); }
}
public int WindowHandle
{
get { return this.windowHandle.ToInt32(); }
}
#region IDisposable Members
public void Dispose()
{
if (excel != null)
{
excel.Workbooks.Close();
excel.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);
excel = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
try
{
Process process = Process.GetProcessById(this.ProcessId);
if (process != null)
{
process.Kill();
}
}
catch
{
}
}
}
#endregion
}
}
using (ExcelWrapper wrapper = new ExcelWrapper())
{
}
The idea is to grab the window handle and get the process ID of the instance of Excel. You try and shut down normally by doing a clearup & just terminate the process if you haven't managed to fully.
If you have correctly tidied up all your objects, you shouldn't need to terminate the process in this way, but it does offer a final 'fail safe'