徹底關閉Excle進程的幾個方法


之前研究過的問題,最近有朋友問,這里再總結下做一個筆記。

我們在應用程序里面通過創建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程序。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM