VB.Net - Excel COM 对象未发布 [英] VB.Net - Excel COM Object not getting released
问题描述
我面临一个问题,即即使在调用 ReleaseComObject 和 GC.Collect 方法后 Excel Process 仍然处于活动状态.
我的 Excel 进程终止,但仅在我关闭用户表单后
以下是示例代码,显示了我为摆脱 Excel Process 所做的一切:
公共类frmTESTPrivate Sub Button1_Click(sender As Object, e As EventArgs) 处理Button1.ClickDim objExcel As xl.ApplicationDim wbReport As xl.Workbook = NothingobjExcel = CreateObject("Excel.Application")尝试wbReport = objExcel.Workbooks.Open("D:ELNicolasVS OnlineClasse A v2Launcher-v2.2ResourcesModulesoom.xlsm")Catch ex 作为例外Common.WriteDebugLog("异常第 44 行")结束尝试如果 wbReport 什么都没有,那么MsgBox("报告错误 - 代码 745.", vbExclamation)退出子万一使用 objExcel.可见=假.ScreenUpdating = 假.Calculation = xl.XlCalculation.xlCalculationManual.DisplayAlerts = 假结束于'' 在这里,我完成了我已删除的所有处理,以使问题更简单使用 objExcel.Calculation = xl.XlCalculation.xlCalculationAutomatic.ScreenUpdating = 真.DisplayAlerts = 真结束于''~~>关闭 &清理wbReport.Close(SaveChanges:=False)objExcel.退出()Me.ReleaseObject(wbReport)Me.ReleaseObject(objExcel)MsgBox("完成")结束子Private Sub ReleaseObject(ByVal obj As Object)尝试Dim intRel As Integer = 0做intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)循环而 intRel >0MsgBox("最终发布的对象#" & intRel)Catch ex 作为例外MsgBox("释放对象时出错" & ex.ToString)obj = 没有最后GC.Collect()结束尝试结束子结束班
<块引用>
更新:根据收到的评论,我对代码进行了更改按照其他线程,但它仍然没有帮助.我的Excel进程终止,但仅在我关闭用户表单后
如果您使用的是 .Net V4 或更高版本,请尝试一下.将所有 Button1_Click
代码移动到一个子例程中,并从 Button1_Click
调用它.这将允许该子例程本地的对象超出范围,从而有资格进行垃圾回收.
然后调用使用 Marshal.AreComObjectsAvailableForCleanup 函数来确定释放 COM 对象需要多少垃圾回收周期.
<块引用>备注
如果托管代码和本机代码之间存在大量具有深度依赖关系图的引用,则清理所有对象可能需要很长时间.每次 GC 运行时,它都会释放一些 RCW,进而释放底层 COM 对象.然后,这些 COM 对象将释放它们的托管引用,并在下一次 GC 运行时提供更多对象可用于清理,这将重新开始该过程.
AreComObjectsAvailableForCleanup 方法为应用程序提供了一种方法来确定需要发生多少次 GC.Collect 和 GC.WaitForPendingFinalizers 循环才能清理所有内容.
Private Sub Button1_Click(sender As Object, e As EventArgs) 处理Button1.ClickExcelWork()清理()结束子私人子 ExcelWork()Dim objExcel As xl.ApplicationDim wbReport As xl.Workbook = NothingobjExcel = CreateObject(Excel.Application")尝试wbReport = objExcel.Workbooks.Open(D:ELNicolasVS OnlineClasse A v2Launcher-v2.2ResourcesModulesoom.xlsm")Catch ex 作为例外Common.WriteDebugLog("Exception line 44")结束尝试如果 wbReport 什么都没有,那么MsgBox(Erreur d'ouverture du Reporting - Code 745.", vbExclamation)退出子万一使用 objExcel.可见=假.ScreenUpdating = 假.Calculation = xl.XlCalculation.xlCalculationManual.DisplayAlerts = 假结束于'' 在这里,我完成了我已删除的所有处理,以使问题更简单使用 objExcel.Calculation = xl.XlCalculation.xlCalculationAutomatic.ScreenUpdating = 真.DisplayAlerts = 真结束于''~~>关闭 &清理wbReport.Close(SaveChanges:=False)objExcel.退出()MsgBox(完成")结束子私人子清理()做GC.Collect()GC.WaitForPendingFinalizers()循环而 Marshal.AreComObjectsAvailableForCleanup结束子
I am facing an issue where Excel Process remains active even after calling ReleaseComObject and GC.Collect method.
My Excel Process terminates but ONLY after I close User Form
Below is sample code which shows what all things I am doing to get rid of Excel Process:
Public Class frmTEST
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim objExcel As xl.Application
Dim wbReport As xl.Workbook = Nothing
objExcel = CreateObject("Excel.Application")
Try
wbReport = objExcel.Workbooks.Open("D:ELNicolasVS OnlineClasse A v2Launcher-v2.2ResourcesModulesoom.xlsm")
Catch ex As Exception
Common.WriteDebugLog("Exception line 44")
End Try
If wbReport Is Nothing Then
MsgBox("Erreur d'ouverture du reporting - Code 745.", vbExclamation)
Exit Sub
End If
With objExcel
.Visible = False
.ScreenUpdating = False
.Calculation = xl.XlCalculation.xlCalculationManual
.DisplayAlerts = False
End With
'' Here I do all my processing which I have removed to make the question more simplified
With objExcel
.Calculation = xl.XlCalculation.xlCalculationAutomatic
.ScreenUpdating = True
.DisplayAlerts = True
End With
''~~> Close & Clean Up
wbReport.Close(SaveChanges:=False)
objExcel.Quit()
Me.ReleaseObject(wbReport)
Me.ReleaseObject(objExcel)
MsgBox("Done")
End Sub
Private Sub ReleaseObject(ByVal obj As Object)
Try
Dim intRel As Integer = 0
Do
intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Loop While intRel > 0
MsgBox("Final Released obj # " & intRel)
Catch ex As Exception
MsgBox("Error releasing object" & ex.ToString)
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class
UPDATE: Based on comments I received, I made changes in my code following the other thread, but it still doesn't help. My Excel Process terminates but ONLY after I close User Form
If you are using .Net V4 or greater, give this a try.
Move all your Button1_Click
code into a subroutine and call it from Button1_Click
. This will allow the objects that are local to that subroutine to go out of scope and thereby be eligible for garbage collection.
Then call a cleanup method that uses the Marshal.AreComObjectsAvailableForCleanup function to determine how many garbage collection cycles are required to free the COM objects.
Remarks
If there are a lot of references between managed and native code with deep dependency graphs it can take a long time for all the objects to clean up. Each time a GC runs it will free up some number of RCWs, which will in turn release the underlying COM objects. Those COM objects will then release their managed references and make more objects available for cleanup the next time a GC runs, which starts the process over again.
The AreComObjectsAvailableForCleanup method provides a way for the application to determine how many cycles of GC.Collect and GC.WaitForPendingFinalizers need to happen in order to clean everything up.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ExcelWork()
Cleanup()
End Sub
Private Sub ExcelWork()
Dim objExcel As xl.Application
Dim wbReport As xl.Workbook = Nothing
objExcel = CreateObject("Excel.Application")
Try
wbReport = objExcel.Workbooks.Open("D:ELNicolasVS OnlineClasse A v2Launcher-v2.2ResourcesModulesoom.xlsm")
Catch ex As Exception
Common.WriteDebugLog("Exception line 44")
End Try
If wbReport Is Nothing Then
MsgBox("Erreur d'ouverture du reporting - Code 745.", vbExclamation)
Exit Sub
End If
With objExcel
.Visible = False
.ScreenUpdating = False
.Calculation = xl.XlCalculation.xlCalculationManual
.DisplayAlerts = False
End With
'' Here I do all my processing which I have removed to make the question more simplified
With objExcel
.Calculation = xl.XlCalculation.xlCalculationAutomatic
.ScreenUpdating = True
.DisplayAlerts = True
End With
''~~> Close & Clean Up
wbReport.Close(SaveChanges:=False)
objExcel.Quit()
MsgBox("Done")
End Sub
Private Sub Cleanup()
Do
GC.Collect()
GC.WaitForPendingFinalizers()
Loop While Marshal.AreComObjectsAvailableForCleanup
End Sub
这篇关于VB.Net - Excel COM 对象未发布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!