Home » excel » vb.net – Unable to kill excel processes

vb.net – Unable to kill excel processes

Posted by: admin May 14, 2020 Leave a comment

Questions:

I am using the followiwing code to do some copying and pasting with excel files:

Imports Excel = Microsoft.Office.Interop.Excel
Imports System.IO
Imports System.Runtime.InteropServices

Private Sub btnCombine_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCombine.Click

    Dim xlAppSource As New Excel.Application
    Dim xlAppTarget As New Excel.Application
    Dim xlWbSource As Excel.Workbook
    Dim xlWbTarget As Excel.Workbook
    Dim xlsheetSource As Excel.Worksheet
    Dim xlsheetTarget As Excel.Worksheet
    Dim xlRangeSource As Excel.Range
    Dim xlRangeTarget As Excel.Range

    Dim Progress As Integer = 0
    pbrProgress.Minimum = 0
    pbrProgress.Maximum = amountOfFiles

    btnCombine.Enabled = False
    btnSelect.Enabled = False
    pbrProgress.Visible = True

    getSaveLocation()
    MakeExcelFile()

    'loop through all excel files to get the required data
    For i = 0 To amountOfFiles - 1


        Dim CurrentFile As String = strFileNames(i)
        Dim IntAmountOfRows As Integer = amountOfRows(CurrentFile)
        Dim intStartOfEmptyRow As Integer = amountOfRows(SummaryLocation)

        xlAppSource.DisplayAlerts = False
        xlAppTarget.DisplayAlerts = False

        'Set current workbook
        xlWbSource = xlAppSource.Workbooks.Open(CurrentFile)
        xlWbTarget = xlAppTarget.Workbooks.Open(SummaryLocation)

        'set current worksheet
        xlsheetSource = xlWbSource.ActiveSheet
        xlsheetTarget = xlWbTarget.ActiveSheet

        'copy range of data from source to target file
        xlRangeSource = xlsheetSource.Range("A2:k" & IntAmountOfRows)
        xlRangeSource.Copy()

        xlRangeTarget = xlsheetTarget.Range("A" & intStartOfEmptyRow)
        xlRangeTarget.PasteSpecial(Excel.XlPasteType.xlPasteValues)

        'save summary file before closing
        xlsheetTarget.SaveAs(SummaryLocation)

        'updating progress bar
        Progress = Progress + 1
        pbrProgress.Value = Progress

    Next

    'close excel
    xlWbSource.Close(True)
    xlWbTarget.Close(True)
    xlAppSource.Quit()
    xlAppTarget.Quit()

    xlAppSource.DisplayAlerts = True
    xlAppTarget.DisplayAlerts = True


    'Cleanup
    Marshal.ReleaseComObject(xlAppSource)
    Marshal.ReleaseComObject(xlAppTarget)
    Marshal.ReleaseComObject(xlWbSource)
    Marshal.ReleaseComObject(xlWbTarget)
    Marshal.ReleaseComObject(xlsheetSource)
    Marshal.ReleaseComObject(xlsheettarget)
    Marshal.ReleaseComObject(xlRangeSource)
    Marshal.ReleaseComObject(xlRangeTarget)

    xlAppSource = Nothing
    xlAppTarget = Nothing
    xlWbSource = Nothing
    xlWbTarget = Nothing
    xlsheetSource = Nothing
    xlsheetTarget = Nothing
    xlRangeSource = Nothing
    xlRangeTarget = Nothing

    MsgBox("Samenvoegen compleet")

    init()

End Sub

I have tried every solution given on SO:

  • Never use 2 points on a line
  • I have tried using marshall.ReleaseComObject
  • I have tried setting the objects to “Nothing”

However, everytime I run the application, there will be 10-20 excel processes still running.

How to&Answers:
Option Explicit

Sub Main()

    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application

    xlApp.Visible = False
    xlApp.DisplayAlerts = False

    Dim xlWb As Workbook
    Set xlWb = xlApp.Workbooks.Open("C:\...\path")

    Dim xlSht As Worksheet
    Set xlSht = xlWb.Sheets(1)

    xlSht.Range("A1") = "message from " & ThisWorkbook.FullName

    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit

End Sub

Works for me every single time and does not leave any Excel processes hanging in the task manager.

Note: if your code breaks at some point and you do not handle the already opened objects properly then they will just hang in the processes tab in the Task Manager. If you haven’t implemented error handling in your code then start here.

just consider this as alternative

Option Explicit

Sub Main()

    On Error GoTo ErrHandler
    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application

    xlApp.Visible = False
    xlApp.DisplayAlerts = False

    Dim xlWb As Workbook
    Set xlWb = xlApp.Workbooks.Open("C:\...\path")

    Dim xlSht As Worksheet
    Set xlSht = xlWb.Sheets(1)

    xlSht.Range("A1") = "message from " & ThisWorkbook.FullName

    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit
    Exit Sub

ErrHandler:
    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit
End Sub

Answer:

The Interop Marshal release doesn't always work because Excel XP and lower suck at releasing. I had to use your loop, but replace the Process.Close() and Process.Quit() with Process.Kill(). Works like a charm. Just be careful that you want ALL versions of excel.exe to be killed, because they will.

I use this:

Workbook.Save()
Workbook.Close()
Application.Quit()

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

Worksheet = Nothing
Workbook = Nothing
Application = Nothing

Dim proc As System.Diagnostics.Process

For Each proc In System.Diagnostics.Process.GetProcessesByName("EXCEL")
proc.Kill()
Next

Answer:

When you do anything with the Excel Interop, it creates a new process.

The problem with killing all Excel processes is that you may kill a process that you are working with. You can kill all processes which have been running for a certain length of time (i.e. from a certain timestamp) with:

Dim proc As System.Diagnostics.Process
Dim info As ManagementObject
Dim search As New ManagementObjectSearcher("SELECT ProcessId FROM Win32_process WHERE caption = 'Excel'")
For Each info In search.Get()

    'The string will give you the time that the process started
    'You can then subtract that from the current time to see if you want to kill the process
    Dim TheString As String = info.GetText(TextFormat.Mof).ToString

    'Kill the process according to its ID
    proc = System.Diagnostics.Process.GetProcessById(Mid$(TheString, _
                                                    (Len(TheString) - 8), 4))
    proc.CloseMainWindow()
    proc.Refresh()
    If proc.HasExited Then GoTo NoKill
    proc.Kill()
NoKill:
Next

You’ll need to add:

Imports System.Management

and add the reference for the ‘System.Management’ to your project.

Answer:

You can obtain the process ID from the Excel.Application hwnd and use that to kill the process safely.