完全關閉Excle進程的幾個方法

以前研究過的問題,最近有朋友問,這裏再總結下作一個筆記。服務器

咱們在應用程序裏面經過建立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程序。

相關文章
相關標籤/搜索