之前研究過的問題,最近有朋友問,這里再總結下做一個筆記。
我們在應用程序里面通過創建Excle應用對象打開Excle的情況下,如果不注意幾個問題,可能無法徹底關閉Excle進程,來考察下面的幾種情況:
public static void startexcel() { var excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = true; var book= excel.Application.Workbooks.Open("D:\\Book1.xlsx"); }
上面的代碼打開了一個工作簿,Excel啟動了一個獨立進程並且呈現界面給用戶,不會再犯方法結束后關閉Excel。這種情況下本意是為了讓用戶決定何時關閉工作簿。
結果,當用戶手工關閉工作簿后,Excle進程沒有關閉,這是因為我們的.NET 托管代碼打開的Excle的非托管代碼,.NET運行時沒有釋放相關的句柄,需要加上下面幾行代碼來釋放:
public static void startexcel() { var excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = true; var book= excel.Application.Workbooks.Open("D:\\Book1.xlsx"); System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); excel = null; GC.Collect(); }
上面的代碼,Marshal.ReleaseComObject 會釋放COM組件對象,這里是excel,然后,代碼設置 excel=null,這樣緊接着執行垃圾回收才有效,否則,無法回收excel句柄。
注意,執行上面的代碼並不會關閉了Excel進程,它只是釋放了Excle進程句柄與.NET運行時的關系。
當用戶在外面手工關閉Excle窗體后,Excle進程才會真正從任務管理器消失。
有朋友可能說,我沒有加上面三行代碼也能夠關閉Excle進程啊。
沒錯,上面的代碼只不過是立即釋放了Excle這種非托管資源。注意到我們的 excle對象是一個局部對象,所以當方法結束后,excle對象已經在方法堆棧上被清空了,只需要在外面合適的時候調用下垃圾回收,即可實現徹底關閉Excle進程的效果:
startexcel(); GC.Collect(); Console.WriteLine("excel close ok.");
如果我們的Excel進程不是由用戶關閉而是要程序自動關閉怎么辦?
這個時候只需要調用Excle應用程序對象的關閉方法即可。
完整的代碼如下,並且下面的代碼演示了Excle進程打開一個宏文件,然后再打開工作簿,處理事件,最后關閉Excle窗體,關閉進程清理資源的功能。
Excle的工作簿保存和關閉事件有時候比較有用,比如保存工作簿的時候就上傳一份工作簿副本到服務器。
public static void startexcel() { var excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = true; excel.Workbooks.Open("C:\\A1000.xla"); var book= excel.Application.Workbooks.Open("D:\\Book1.xlsx"); excel.WorkbookBeforeSave += Excel_WorkbookBeforeSave; excel.WorkbookBeforeClose += Excel_WorkbookBeforeClose; book.Close(); excel.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); excel = null; GC.Collect(); } private static void Excel_WorkbookBeforeClose(Workbook Wb, ref bool Cancel) { Console.WriteLine("Excel 關閉,title:" + Wb.Title); } private static void Excel_WorkbookBeforeSave(Workbook Wb, bool SaveAsUI, ref bool Cancel) { Console.WriteLine("Excel保存,title:"+Wb.Title); }
注:
本文的做法,也適用於關閉Word等其它Office程序。