How to Terminate a Windows Process Using VBA (Shell, WMI, and API Methods)

Following my previous post on working with Windows processes, specifically:

this article explores different techniques for terminating a Windows process using VBA.
 

⚠️ Important
These techniques forcibly terminate processes. They do not perform a graceful shutdown and do not allow users to save work. Whenever possible, automation (COM, application object models, etc.) should be used instead. However, in situations where that isn’t possible, these methods can be extremely useful.
 

When Should You Kill a Process with VBA?

Programmatically terminating a process can be useful when:

  • An application has become unresponsive
  • Embedded applications fail to close properly
  • Cleanup is required after automation failures
  • A controlled environment requires strict process management

Below are three commonly used approaches:

  1. Shell + TaskKill (simplest)
  2. WMI (recommended)
  3. Windows API (advanced)

 

Method 1: Using Shell and the Windows TaskKill Command

The simplest way to terminate a process by PID in VBA is to call the Windows taskkill command using Shell.

Public Sub Process_TerminateByPID_Shell(ByVal lPID As Long)
    Call Shell("TaskKill /PID " & lPID & " /F", vbHide)
End Sub

Pros

  • Very easy to implement
  • No additional references required

Cons

  • No confirmation that the process was terminated
  • Relies on the command prompt
  • Limited error handling

You could add a WMI check afterward, but at that point it makes more sense to use WMI directly.
 

Method 2: Terminating a Process Using WMI (Recommended)

The WMI approach is more robust and allows you to validate whether the termination was successful. This makes it a better choice for production code.

Public Function Process_TerminateByPID_WMI(ByVal lPID As Long) As Boolean
    On Error GoTo Error_Handler
    Dim oWMI                  As Object
    Dim oCols                 As Object
    Dim oCol                  As Object
    Dim sWQL                  As String
    Dim lRetVal                As Long
    Const wbemFlagReturnImmediately = 16    '(&H10)
    Const wbemFlagForwardOnly = 32          '(&H20)

    sWQL = "SELECT ProcessID FROM Win32_Process Where ProcessID = " & lPID

    Set oWMI = GetObject("winmgmts:\\.\root\cimv2")
    Set oCols = oWMI.ExecQuery(sWQL, , wbemFlagReturnImmediately Or wbemFlagForwardOnly)
    For Each oCol In oCols
        lRetVal = oCol.Terminate
        If lRetVal = 0 Then Process_TerminateByPID_WMI = True
    Next

Error_Handler_Exit:
    On Error Resume Next
    Set oCol = Nothing
    Set oCols = Nothing
    Set oWMI = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: Process_TerminateByPID_WMI" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

Why Use WMI?

  • No external commands required
  • Return value confirms success or failure
  • Easily extended to even terminate processes by name or owner

 

Method 3: Using the Windows API

For completeness, you can also terminate a process using the Windows API. This provides low-level control but is more complex and may require conditional compilation for 32-bit and 64-bit Office.

Private Declare PtrSafe Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As LongPtr
Private Declare PtrSafe Function TerminateProcess Lib "kernel32" (ByVal hProcess As LongPtr, ByVal uExitCode As Long) As Long
Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long
Private Const PROCESS_TERMINATE As Long = &H1


Public Function Process_TerminateByPID_API(ByVal PID As Long) As Boolean
    On Error GoTo Error_Handler
    Dim hProcess              As LongPtr
    Dim lRetVal               As Long

    ' Open the process with terminate rights
    hProcess = OpenProcess(PROCESS_TERMINATE, 0, PID)
    If hProcess <> 0 Then
        lRetVal = TerminateProcess(hProcess, 0)    ' Terminate the process
        CloseHandle hProcess    ' Close the handle
        If lRetVal <> 0 Then Process_TerminateByPID_API = True
    'Else
        ' MsgBox "Could not open process " & PID & "."
    End If

Error_Handler_Exit:
    On Error Resume Next
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: Process_TerminateByPID_API" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

 

Which Method Should You Use?

Method Complexity Validation Recommendation
Shell + TaskKill Low No Quick scripts only
WMI Medium Yes Best overall choice
Windows API High Yes Advanced scenarios

 

Final Thoughts

While forcibly terminating processes should always be a last resort, VBA provides several reliable ways to do so when necessary. In most cases, the WMI approach offers the best balance of simplicity, reliability, and control.