使用EXCEL产生报表,再VB6时我们会使用CreateObject开始,
再以Set Nothing 结束,就OK了~
但在.NET并不是这么简单就可以释放记忆体,
每执行一次,工作管理员又会产生一次EXCEL.EXE
网路上查到许多使用GC.Collect()来强制回收,
也有看到Kill Process的...
但这样强制系统回收....总觉得这样好像哪里不妥,
若不到最后,我想我应该不会使用这方法去强制影响系统的运作,
而且这在Client端程式可以这样执行,到Server端执行又不行~"~
一开始我还想说是权限问题~测了很久....

想说干脆执行一次CreateObject,后续使用getObject重复使用该Object就好,结果...
又是Client可以,Server端不行,~"~
查到最后...是有Server.CreateObject 却没有 Server.GetObject

之后回归最原始的方式,
再仔细看微软的支援页面,.NET 2.0之后可使用以下程式来回收记忆体
System.Runtime.InteropServices.Marshal.FinalReleaseComObject
我就从每一层结束都做FinalReleaseComObject
结果发现,只写以下就可以释放EXCEL.EXE的记忆体

Dim xlapp As Excel.Application = Server.CreateObject("Excel.Application")
xlapp.Quit()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlapp)
xlapp = Nothing

但只要再中间加上下列开启档案....

Dim xlBook As Workbook = xlapp.Workbooks.Open(wkPath & "\sample.xlsx")
xlBook.Close()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlBook)
xlBook = Nothing

EXCEL.EXE就会出现在工作管理员中屹立不摇...
之后再想到根本,EXCEL的组成元素如下,
Application、Workbooks、Workbook、Worksheet、Range
所以就每一层都SET NEW 用完都做FinalReleaseComObject
每一层都需要正常开始与结束就可以正确释放记忆体
这样写CODE写得有点复杂,不过记忆体真的可以正常释放,
只要其中一个环节没有做到EXCEL.EXE就会在工作管理员中,

范例是读取现有EXCEL挡,之后修改内容后关闭储存~

Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices.Marshal
 
Sub Excel()
    Dim xlApp As New Excel.Application
    Dim xlBooks As Excel.Workbooks = xlApp.Workbooks
    Dim xlBook = xlBooks.Open("D:\sample.xlsx")
    Dim xlSheet As Excel.Worksheet = xlBook.ActiveSheet
    Dim xlRange As Excel.Range
    xlApp.Visible = False
    xlApp.DisplayAlerts = False
    xlRange = xlSheet.Range("A1")
    xlRange.Value = 123
    FinalReleaseComObject(xlRange)
    FinalReleaseComObject(xlSheet)
    xlBook.Save()
    xlBook.Close()
    FinalReleaseComObject(xlBook)
    FinalReleaseComObject(xlBooks)
    xlApp.Quit()
    FinalReleaseComObject(xlApp)
End Sub


参考资料:http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109&#appliesto

 
~Shael

 

相关文章