关于VSTO调用Excel后进程无法退出的解决方案:

VSTO的Excel对象模型提供了托管代码对Excel的操作。但是它的实现时通过RCW(Runtime Com Wrapper)实现的,所以无法完全按照托管代码的运行方式操作。COM的资源释放时通过引用计数的方式实现,不同于CLR的GC机制,在引用计数没有设置为0的情况下,是不会回收资源的。所以,很多情况下,在操作Excel的时候,进程无法结束,其实就是因为Excel的COM计数器没有置0.

那么,如何才能正确地将计数器置0呢?简单代码如下。

            //启动Excel的程序
            Excel.Application app = new Excel.Application();

            //获取Excel的所有工作簿,注意,不可以使用.net级联方式,即如app.Workbooks.Add()
            //必须每个变量都设置引用,这样才可以逐个释放变量,切记,重中之重
            Excel.Workbooks wbs = app.Workbooks;
            //获取一个工作簿
            Excel.Workbook wb = wbs.Add();
            //获取当前工作表
            Excel.Worksheet ws = wb.ActiveSheet;

            //声明一个表示Excel区域的变量,并利用其对Excel进行操作
            Excel.Range rng;
            rng = ws.Range["A1"];
            rng.Value2 = "Hello";
            //将该变量引用的Com对象的计数器设置为0,并设置引用为null,释放对象
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(rng);
            rng = null;
            //同上
            rng = ws.Range["A2"];
            rng.Value2 = "Again";
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(rng);
            rng = null;

            //释放工作表
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ws);
            ws = null;

            //释放工作簿集合
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wbs);
            wbs = null;

            //保存文档
            wb.SaveAs(@"d:\hello.xlsx");

            //释放工作簿
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wb);
            wb = null;

            //通知Excel主机退出程序
            app.Quit();

            //最后,释放Excel主机的引用计数器
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app);
            app = null;

如此,进程中的Excel将自动退出,我们也就避免强制结束进程带来的Excel报错问题。

这里的要点就是:任何一个Com对象的引用在指向其他对象之前必须显示释放其对该Com的引用。最后,释放所有的Excel对象的引用计数!

 

posted @ 2013-07-17 11:16  kennywangjin  阅读(1323)  评论(0编辑  收藏  举报