以前研究過的問題,最近有朋友問,這裏再總結下作一個筆記。服務器
咱們在應用程序裏面經過建立Excle應用對象打開Excle的狀況下,若是不注意幾個問題,可能沒法完全關閉Excle進程,來考察下面的幾種狀況:ui
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。這種狀況下本意是爲了讓用戶決定什麼時候關閉工做簿。spa
結果,當用戶手工關閉工做簿後,Excle進程沒有關閉,這是由於咱們的.NET 託管代碼打開的Excle的非託管代碼,.NET運行時沒有釋放相關的句柄,須要加上下面幾行代碼來釋放:excel
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句柄。code
注意,執行上面的代碼並不會關閉了Excel進程,它只是釋放了Excle進程句柄與.NET運行時的關係。對象
當用戶在外面手工關閉Excle窗體後,Excle進程纔會真正從任務管理器消失。blog
有朋友可能說,我沒有加上面三行代碼也可以關閉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程序。