C# 调用Office Excel 接口方法Quit(),但是Excel进程不退出的解决办法

相信在C# 中使用过EXCEL的人都遇到过调用 ExcelApplication.Quit() ,但是 Excel进程依然存在的情况:


Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.ApplicationClass();

//Do your work...

excelApp.Quit()


GOOGLE了许多中文帖子,最终都是强行调用 Process.kill() 草草了事。其实解决方案就在微软的网站上:


http://support.microsoft.com/kb/Q317109


看了这个以后,根源其实就在引用计数:

当 Visual Studio .NET 从托管代码调用 COM 对象时,它自动创建运行库可调用包装 (RCW)。RCW 封送 .NET 应用程序和 COM 对象之间的调用。RCW 保留着对 COM 对象的引用计数。因此,如果 RCW 上没有将所有引用全部释放,COM 对象就不会退出。

简单的说,就是栈内存中,依然有对象引用存在,RCW我推测是堆内存中的一段区域,栈内存中的对象指向了堆内存,所以GC就认为这一段堆内存依然有用,就不会去释放它。


所以,最终的解决方案其实就如这个链接指出的:


  • 要确保退出 Office 应用程序,自动化代码一定要满足以下条件:
    • 将每个对象声明为新变量。例如,将下面的代码行
      oBook = oExcel.Workbooks.Add()
      					
      更改为以下内容:
      dim oBooks as Excel.Workbooks
      oBooks = oExcel.Workbooks
      oBook = oBooks.Add()
      					
    • 停止使用某个对象时,应使用 System.Runtime.InteropServices.Marshal.ReleaseComObject。这样可以减少 RCW 的引用计数。
    • 要释放对变量的引用,请将变量设置为等于 NothingNull
    • 使用 Office 应用程序对象的 Quit 方法通知服务器关闭。
也就是说,一个堆对象,对应一个栈对象,这样当遇到区域截至符 } 的时候,这个栈对象就被析构了,所以对应的引用计数 -1.  Application.Quit() 就能工作正常了。

展开阅读全文

没有更多推荐了,返回首页