在ASP.NET或C#窗体应用中,经常需要创建Excel的COM对象,使用后应该关闭该对象,并在Windows的任务窗体中清除Excel进程。下面程序即是一个标准的清除过程:
private void Close( )
{
if (border != null) // 为Excel.Border 对象
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(border);
border = null;
}
if (range != null) // 为 Excel.Range对象
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
range = null;
}
for (int k = 1; k <= book.Worksheets.Count; k++)
{
Excel.Worksheet ws = (Excel.Worksheet)book.Worksheets[k];
System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
ws = null;
}
if (book != null) // Excel.WorkBook 对象
{
book.Close(false, Missing.Value, Missing.Value);
System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
book = null;
}
if (app != null) // Excel.ApplicationClass 对象
{
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
}
}
上述代码,一般可以清除创建的Excel.ApplicationClass进程,但某些时候却实现的不好,即没有清除干净,导致在一个应用程序中创建多个Excel对象。改进的方法是,在上述代码中加入如下语句,可以清除Excel进程。
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
不过,这种强制搜集内存的操作效率比较低。现介绍一可行的清除进程的方法,代码如下:
[DllImportAttribute("User32.dll")]private static extern IntPtr FindWindow(String ClassName, String WindowName);
private IntPtr GetExcelWinHandle(Excel.ApplicationClass xlsApplication)
{
xlsApplication.ActiveWindow.Caption = "xls" + DateTime.Now.ToString("HHmmssfff"); // 注意名称的唯一性,该设置是本方法的关键
string winName = "Microsoft Excel - " + xlsApplication.ActiveWindow.Caption; // 关键
IntPtr hWnd = FindWindow(null, winName);
return hWnd;
}
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int procId);
private void CloseExcel(Excel.ApplicationClass xlsObj)
{
IntPtr hWnd = GetExcelWinHandle(xlsObj);
if (hWnd != IntPtr.Zero)
{
int pid = 0;
GetWindowThreadProcessId(hWnd, out pid); //得到本进程唯一标志pid
if (pid != 0)
{
System.Diagnostics.Process xlsProc = System.Diagnostics.Process.GetProcessById(pid); //得到对进程pid的引用
if (xlsProc != null)
{
xlsProc.Kill();
}
}
}
}
调用上述代码CloseExcel()方法即可清除进程。其过程为:先用 GetExcelWinHandle()方法获取Excel的窗体句柄,然后通过该句柄找到进程标识PID,最后kill该进程pid即可。上述代码的关键点,是设置Excel.ApplicationClass对象的ActiveWindow.Caption,通过该Caption和Windows API函数FindWindow即可找到Excel的窗体句柄。
上述代码使用C# 2005编程,并在XP下测试成功。