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实例,代码如下:

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进程的。
标签:
C#疑难杂症
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)