C#中通過com組件操作excel不能關閉的問題

問題:

當用如下代碼操作完Excel,雖然調用了Application的Quit()方法,但發現Excel進程並沒退出。

           object missing = System.Reflection.Missing .Value;
            Application app = new Application();
            app.Visible = false ;
            app.UserControl = true ;
            Workbook wb = app.Workbooks.Open(path, missing, true , missing, missing, missing, missing,
                        missing, missing, true , missing, missing, missing, missing, missing);
            Worksheet ws = (Worksheet )wb.Worksheets.get_Item(1);
            Console .WriteLine(ws.Cells[2,1].Value);
            ws.Close();
            ws = null;
            app.Quit();
            app = null;

結果:



原因:
When Visual Studio .NET calls a COM object from managed code, it automatically creates a Runtime Callable Wrapper (RCW). The RCW marshals calls between the .NET application and the COM object. The RCW keeps a reference count on the COM object. Therefore, if all references have not been released on the RCW, the COM object does not quit.

解決方案:

1、爲每一個對象定義一個變量。
例如:
把這段代碼
Workbook wb = wbs.Open(path, missing, true , missing, missing, missing, missing,
                        missing, missing, true , missing, missing, missing, missing, missing);
改爲
Workbooks wbs = app.Workbooks;
Workbook wb = wbs.Open(path, missing, true , missing, missing, missing, missing,
                        missing, missing, true , missing, missing, missing, missing, missing);

2、當使用完com對象對其循環調用System.Runtime.InteropServices.Marshal.ReleaseComObject 直到返回值爲0
3、設置變量位null
4、調用Quit方法通知服務器關閉
5、調用GC .Collect();

最終:
把上邊的代碼修改爲:
        public static void ExcelRead(string path)
        {

            object missing = System.Reflection.Missing.Value;
            Application app = new Application();
            app.Visible = false;
            app.UserControl = true;
            Workbooks wbs = app.Workbooks;
            Workbook wb = wbs.Open(path, missing, true, missing, missing, missing, missing,
                        missing, missing, true, missing, missing, missing, missing, missing);
            Sheets wss = wb.Worksheets; 
            Worksheet ws = (Worksheet)wss.get_Item(1);
            Console.WriteLine(ws.Cells[2,1].Value);
            NAR(ws);
            ws = null;
            NAR(wss);
            wss = null;
            wb.Close();
            NAR(wb);
            wb = null;
            wbs.Close();
            NAR(wbs);
            wbs = null;
            app.Quit();
            NAR(app);
            app = null;
            GC.Collect();
        }
        private static void NAR(object o)
        {
            try
            {
                while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;

            }
            catch
            { }
            finally
            {
                o = null;
            }
        }
    
結果能正常關閉Excel進程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章