Excel COM 物件採用**單執行緒套間 (STA)** 模型,所有操作必須在同一執行緒且**嚴格按建立順序反向釋放**。任何 RCW (Runtime Callable Wrapper) 洩漏都會導致 Excel 進程殘留。
Excel.Application excel = null;
Excel.Workbook workbook = null;
Excel.Worksheet worksheet = null;
try
{
excel = new Excel.Application();
workbook = excel.Workbooks.Open(path, ..., false, ...);
excel.Visible = true;
worksheet = (Excel.Worksheet)workbook.Worksheets[1];
// 業務操作...
if (!excel.ActiveWorkbook.Saved) excel.ActiveWorkbook.Save();
}
finally
{
// 1. 釋放工作表
if (worksheet != null) Marshal.ReleaseComObject(worksheet);
// 2. 釋放工作簿
if (workbook != null) Marshal.ReleaseComObject(workbook);
// 3. 退出並釋放應用程式
if (excel != null)
{
excel.Quit();
Marshal.ReleaseComObject(excel);
}
// 4. 強制 GC 回收 RCW
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect(); // 第二次確保 Finalizer 執行完成
}
excel.Workbooks.Open() 會產生臨時 Workbooks RCW 洩漏。拆分為 var wbs = excel.Workbooks; workbook = wbs.Open(...); Marshal.ReleaseComObject(wbs);Excel 本身是非托管 COM 伺服器。RCW 是托管包裝器。**我們釋放的是 RCW**,讓 COM 參考計數歸零,Excel 自行關閉。這與「檔案流屬於非托管資源」不同層面,勿混淆。
「嚴格反向釋放 + 兩次 GC.Collect」是操作 Excel Interop 的鐵律。理解 RCW/COM 參考計數機制,比盲目複製代碼更能應對複雜場景。新專案優先考慮免 COM 庫,徹底避開進程殘留噩夢。