Share via

I cannot close Excel after using it in VB.net

Devon Nullman 100 Reputation points
2026-04-29T18:55:05.6533333+00:00

I use vb.net to grab data from a spreadsheet using a background worker, when the data is finished loading I want to close excel but it leaves excel as a background task. The loading seems fine based on the program behavior. Here is the code:

Private Sub BGWLoadData_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BGWLoadData.RunWorkerCompleted

LblProgress.Text = ""

TxtQuery.Enabled = True

Label1.Text = "Start Typing:"

'Data loaded, now try to close Excel for real. . . .

xlWorkSheet = Nothing

xlWorkBook.Close()

xlWorkBook = Nothing

xlApp.Quit()

xlApp = Nothing

releaseObject(xlApp)

releaseObject(xlWorkBook)

releaseObject(xlWorkSheet)

End Sub

Private Sub releaseObject(ByVal obj As Object)

If obj Is Nothing Then

Exit Sub

End If

Try

System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)

obj = Nothing

Catch ex As Exception

obj = Nothing

Finally

GC.Collect()

End Try

End Sub

No matter what I try, a background excel task is created

Developer technologies | VB

Answer accepted by question author

  1. Q&A Assist
    2026-04-29T18:55:16.7033333+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    Excel remains as a background task because the Runtime Callable Wrapper (RCW) for the COM objects is still holding references to Excel. Simply setting variables to Nothing and calling ReleaseComObject once is not always enough.

    Use the pattern from the documented resolution: explicitly release each COM object in the correct order, looping ReleaseComObject (or using FinalReleaseComObject in .NET 2.0+), and only then force garbage collection if needed.

    Example adapted to VB.NET:

    Private Sub NAR(ByVal o As Object)
        Try
            While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
            End While
        Catch
        Finally
            o = Nothing
        End Try
    End Sub
    
    Private Sub BGWLoadData_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) _
        Handles BGWLoadData.RunWorkerCompleted
    
        LblProgress.Text = ""
        TxtQuery.Enabled = True
        Label1.Text = "Start Typing:"
    
        ' Release in reverse order of creation/use
        NAR(xlWorkSheet)
    
        xlWorkBook.Close(False)
        NAR(xlWorkBook)
    
        ' If you have xlWorkBooks collection, release it too
        ' NAR(xlWorkBooks)
    
        xlApp.Quit()
        NAR(xlApp)
    
        ' Optional: if Excel still does not exit
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Sub
    

    Key points:

    1. Release every Excel COM object that was created (Application, Workbooks, Workbook, Worksheet, etc.).
    2. Release them in reverse order of creation (child objects first, then parent, then Application).
    3. Use a loop with Marshal.ReleaseComObject (or Marshal.FinalReleaseComObject in .NET 2.0 and later) to ensure all RCW references are released.
    4. Only after all COM objects are released, optionally call GC.Collect() and GC.WaitForPendingFinalizers() if Excel still does not shut down.

    Following this pattern causes the Excel process to exit once the last COM reference is released.


    References:

1 additional answer

Sort by: Most helpful
  1. Nancy Vo (WICLOUD CORPORATION) 3,550 Reputation points Microsoft External Staff Moderator
    2026-04-30T06:14:02.6533333+00:00

    Hello @Devon Nullman ,

    Thanks for your question.

    You can not close Excel after using it in VB.net because:

    • releaseObject is called after = Nothing. Once you set xlApp = Nothing, VB.NET forgets where Excel is. Passing it to releaseObject after that is like trying to return something you already threw in the trash, the function receives Nothing and immediately exits without releasing anything.
    • Wrong order of releasing objects You must release from innermost → outermost: xlWorkSheet first, then xlWorkBook, then xlApp. Releasing in the wrong order leaves dangling COM references.
    • GC.Collect() alone just starts the cleanup but doesn't wait for it to finish. Excel stays in memory until cleanup is fully completed.

    You can refer to following code example:

    
    Private Sub BGWLoadData_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) _
        Handles BGWLoadData.RunWorkerCompleted
    
        LblProgress.Text = ""
        TxtQuery.Enabled = True
        Label1.Text = "Start Typing:"
    
    
        If xlWorkBook IsNot Nothing Then
            xlWorkBook.Close(False)
        End If
    
        If xlApp IsNot Nothing Then
            xlApp.Quit()
        End If
    
    
        releaseObject(xlWorkSheet)
        releaseObject(xlWorkBook)
        releaseObject(xlApp)
    
        xlWorkSheet = Nothing
        xlWorkBook = Nothing
        xlApp = Nothing
    
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
    
    End Sub
    
    
    Private Sub releaseObject(ByVal obj As Object)
    
        If obj Is Nothing Then
            Exit Sub
        End If
    
        Try
            Dim remainingRefs As Integer = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
            While remainingRefs > 0
                remainingRefs = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
            End While
    
        Catch ex As Exception
            Console.WriteLine("Error releasing object: " & ex.Message)
        Finally
            obj = Nothing
        End Try
    
    End Sub
    

    I hope this addresses your question. If this response was helpful, please consider following the guidance to provide feedback.


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.