VB.Net - Excel COM 对象未被释放

VB.Net - Excel COM Object not getting released

我遇到一个问题,即使在调用 ReleaseComObject 和 GC.Collect 方法后,Excel 进程仍然处于活动状态。

我的 Excel 进程终止,但仅在我关闭用户表单后终止

下面是示例代码,显示了我为摆脱 Excel 过程所做的所有事情:

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:\EL\Nicolas\VS Online\Classe A v2\Launcher-v2.2\Resources\Modules\Zoom.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

如果您使用的是 .Net V4 或更高版本,请尝试一下。 将所有 Button1_Click 代码移动到子例程中并从 Button1_Click 调用它。这将允许该子例程本地的对象超出范围,从而有资格进行垃圾收集。

然后调用使用 Marshal.AreComObjectsAvailableForCleanup 函数的清理方法来确定释放 COM 对象需要多少次垃圾回收周期。

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:\EL\Nicolas\VS Online\Classe A v2\Launcher-v2.2\Resources\Modules\Zoom.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