zoukankan      html  css  js  c++  java
  • C#强制关闭Excel进程(通过COM使用Excel时)

    在之前的一个项目中,客户要求要出Excel的报表。

    由于其报表比较复杂,所以我们采用先制作报表的Excel模板,然后再通过COM将数据写入Excel模板中(缺点就是要求部署的机器上有Excel)。

    刚开始做的时候挺顺利,做完之后也能按要求完成报表。但是时间长了服务器会变慢,打开windows的进程管理器一看,才发现里面有很多的Excel.exe的进程。原因就是每次调用COM后产生的Excel.exe的进程没有正常关闭掉。

    分析其中的原因,我觉得可能就是COM中的类毕竟是非托管代码,即使我们在程序里释放了new出来的相关类(比如Excel.Application,Excel.Workbooks等等)。但是.net的GC可能并没有及时的回收这些通过COM调用的类。从而导致有许多Excel.exe的进程驻留在操作系统中。

    既然有这方面的问题,就要对这些的进程进行强制回收,避免服务器上的进程越来越多,最后导致系统的崩溃。

    本次采用强制Kill掉进程的方式来释放资源的,如果有更好的方法,希望各位高手不吝指教!

    本方法通过封装一个ExcelInstances的类来手动管理Excel实例,代码如下:

    ExcelInstances
    public class ExcelInstances
    {
    private static Microsoft.Office.Interop.Excel.Application m_excelApp = null;
    private static Microsoft.Office.Interop.Excel.Workbooks m_excelWorkBooks = null;

    [DllImport(
    "User32.dll")]
    public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int Processid);

    private ExcelInstances()
    {
    }



    // 初始化ExcelInstances后,生成相应的COM实例

    private static void Init()
    {
    if (m_excelApp == null)
    {
    m_excelApp
    = new Microsoft.Office.Interop.Excel.Application();
    m_excelApp.DisplayAlerts
    = false;
    m_excelApp.AlertBeforeOverwriting
    = false;
    }

    if (m_excelWorkBooks == null)
    {
    if (m_excelApp != null)
    {
    m_excelWorkBooks
    = m_excelApp.Workbooks;
    }
    }
    }



    // 辅助功能-获取当前系统中Excel的进程数

    public static int GetExcelProcessCount()
    {
    int iReturn = 0;
    System.Diagnostics.Process[] pProcesses
    = null;

    try
    {
    pProcesses
    = System.Diagnostics.Process.GetProcesses();

    foreach (System.Diagnostics.Process p in pProcesses)
    {
    if (string.Equals(p.ProcessName.ToString(), "EXCEL"))
    {
    iReturn
    ++;
    }
    }
    }
    catch (Exception e)
    {
    throw e;
    }

    return iReturn;
    }



    // 强行关闭指定的Excel进程

    public static void Kill(Microsoft.Office.Interop.Excel.Application theApp)
    {
    int iId = 0;
    IntPtr intptr
    = new IntPtr(theApp.Hwnd);
    System.Diagnostics.Process p
    = null;

    try
    {
    GetWindowThreadProcessId(intptr,
    out iId);
    p
    = System.Diagnostics.Process.GetProcessById(iId);

    if (p != null)
    {
    p.Kill();
    p.Dispose();
    }

    }
    catch (Exception e)
    {
    throw e;
    }
    }

    private static ExcelInstances _objInstances = null;



    // 获得一个ExcelInstances 的实例

    public static ExcelInstances GetInstances()
    {
    if (_objInstances == null)
    {
    _objInstances
    = new ExcelInstances();
    }

    Init();

    return _objInstances;
    }

    // 按照文件名获得指定的workbook
    public Microsoft.Office.Interop.Excel.Workbook GetWorkBook(string strFileName)
    {
    return m_excelWorkBooks.Add(strFileName);
    }

    // 关闭workbook
    public void Close()
    {
    try
    {
    if (m_excelWorkBooks != null)
    {
    m_excelWorkBooks.Close();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(m_excelWorkBooks);
    m_excelWorkBooks
    = null;
    }

    if (m_excelApp != null)
    {
    m_excelApp.Quit();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(m_excelApp);
    m_excelApp
    = null;
    }
    }
    catch (Exception e)
    {
    throw e;
    }
    }
    }

    其中的Kill方法就是用来强行关闭Excel进程的。

  • 相关阅读:
    P3382 【模板】三分法
    1269: [AHOI2006]文本编辑器editor
    1500: [NOI2005]维修数列
    4196: [Noi2015]软件包管理器
    django 表单系统 之 forms.ModelForm
    django 表单系统 之 forms.Form
    django ORM 批量操作:批量插入bulk_create
    django 多数据库时 ORM语句 选择数据库
    django 配置 多数据库
    django模板复用 extends,block,include
  • 原文地址:https://www.cnblogs.com/wang_yb/p/1726135.html
Copyright © 2011-2022 走看看