在 C# / ASP.NET 中使用 Microsoft.Office.Interop.Excel 自動化 Excel 時,常遇到 Excel.exe 進程殘留 的問題,尤其在 Web 環境下更為嚴重。傳統釋放 COM 物件、呼叫 GC.Collect() 等方法並非萬全,且 GC.Collect() 會影響整個 CLR 效能。
利用 Windows API GetWindowThreadProcessId 取得 Excel 視窗對應的進程 ID,再呼叫 Process.Kill() 強制結束,確保只關閉當前自動化啟動的實例,不影響其他使用者的 Excel。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
public class ExcelHelper
{
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int lpdwProcessId);
public void OpenAndCloseExcel(string filePath)
{
Application excel = new ApplicationClass();
try
{
Workbook wb = excel.Workbooks.Open(filePath,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
// 取得視窗控制代碼與進程 ID
IntPtr hwnd = new IntPtr(excel.Hwnd);
GetWindowThreadProcessId(hwnd, out int procId);
// 依進程 ID 取得 Process 物件並終止
Process proc = Process.GetProcessById(procId);
proc.Kill(); // 強制結束
}
finally
{
// 釋放 COM 物件(建議搭配使用)
if (excel != null) Marshal.ReleaseComObject(excel);
}
}
}
excel.Hwnd)反查進程 ID,精準鎖定目標。Quit()、釋放 COM 物件,最後再用此法兜底殺掉殘留進程。透過 Windows API 精準取得進程 ID 並強制終止,是目前最可靠、副作用最小的關閉 Excel 進程方案。搭配正確的 COM 物件釋放流程,可徹底解決「Excel.exe 不關閉」的困擾。