在之前的一個項目中,客戶要求要出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;
}