HuLihui's Blog

Think out of box, there is always a better way.

.NET程序中如何清除Excel的COM对象

    在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下测试成功。



阅读更多
想对作者说点什么? 我来说一句

c#开发Excel报表

2012年06月28日 38KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭