Following my previous post on working with Windows processes, specifically:
this article explores different techniques for terminating a Windows process using VBA.
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:
- Shell + TaskKill (simplest)
- WMI (recommended)
- 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.