How to find and terminate running applications
Posted on January 5, 2009
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | 'System & API - How to find and terminate running applications Option Explicit Const MAX_PATH& = 260 Declare Function TerminateProcess Lib "kernel32" (ByVal ApphProcess As Long, _ ByVal uExitCode As Long) As Long Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _ ByVal blnheritHandle As Long, ByVal dwAppProcessId As Long) As Long Declare Function ProcessFirst Lib "kernel32" Alias "Process32First" (ByVal hSnapshot As Long, _ uProcess As PROCESSENTRY32) As Long Declare Function ProcessNext Lib "kernel32" Alias "Process32Next" (ByVal hSnapshot As Long, _ uProcess As PROCESSENTRY32) As Long Declare Function CreateToolhelpSnapshot Lib "kernel32" Alias "CreateToolhelp32Snapshot" _ (ByVal lFlags As Long, lProcessID As Long) As Long Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Private Type LUID lowpart As Long highpart As Long End Type Private Type TOKEN_PRIVILEGES PrivilegeCount As Long LuidUDT As LUID Attributes As Long End Type Const TOKEN_ADJUST_PRIVILEGES = &H20 Const TOKEN_QUERY = &H8 Const SE_PRIVILEGE_ENABLED = &H2 Const PROCESS_ALL_ACCESS = &H1F0FFF Private Declare Function GetVersion Lib "kernel32" () As Long Private Declare Function GetCurrentProcess Lib "kernel32" () As Long Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, _ ByVal DesiredAccess As Long, TokenHandle As Long) As Long Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" _ (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, _ ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, _ PreviousState As Any, ReturnLength As Any) As Long Type PROCESSENTRY32 dwSize As Long cntUsage As Long th32ProcessID As Long th32DefaultHeapID As Long th32ModuleID As Long cntThreads As Long th32ParentProcessID As Long pcPriClassBase As Long dwFlags As Long szexeFile As String * MAX_PATH End Type Public Function KillApp(myName As String) As Boolean Const TH32CS_SNAPPROCESS As Long = 2& Const PROCESS_ALL_ACCESS = 0 Dim uProcess As PROCESSENTRY32 Dim rProcessFound As Long Dim hSnapshot As Long Dim szExename As String Dim exitCode As Long Dim myProcess As Long Dim AppKill As Boolean Dim appCount As Integer Dim i As Integer On Local Error GoTo Finish appCount = 0 uProcess.dwSize = Len(uProcess) hSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&) rProcessFound = ProcessFirst(hSnapshot, uProcess) Do While rProcessFound i = InStr(1, uProcess.szexeFile, Chr ( 0 ) ) szExename = LCase$(Left$(uProcess.szexeFile, i - 1)) If Right$(szExename, Len(myName)) = LCase$(myName) Then KillApp = True appCount = appCount + 1 myProcess = OpenProcess(PROCESS_ALL_ACCESS, False, uProcess.th32ProcessID) If KillProcess(uProcess.th32ProcessID, 0) Then 'For debug.... Remove this MsgBox "Instance no. " & appCount & " of " & szExename & " was terminated!" End If End If rProcessFound = ProcessNext(hSnapshot, uProcess) Loop Call CloseHandle(hSnapshot) Exit Function Finish: MsgBox "Error!" End Function 'Terminate any application and return an exit code to Windows. Function KillProcess(ByVal hProcessID As Long, Optional ByVal exitCode As Long) As Boolean Dim hToken As Long Dim hProcess As Long Dim tp As TOKEN_PRIVILEGES If GetVersion() >= 0 Then If OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES Or _ TOKEN_QUERY, hToken) = 0 Then GoTo CleanUp End If If LookupPrivilegeValue("", "SeDebugPrivilege", tp.LuidUDT) = 0 Then GoTo CleanUp End If tp.PrivilegeCount = 1 tp.Attributes = SE_PRIVILEGE_ENABLED If AdjustTokenPrivileges(hToken, False, tp, 0, ByVal 0&, ByVal 0&) = 0 Then GoTo CleanUp End If End If hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, hProcessID) If hProcess Then KillProcess = (TerminateProcess(hProcess, exitCode) <> 0) ' close the process handle CloseHandle hProcess End If If GetVersion() >= 0 Then ' under NT restore original privileges tp.Attributes = 0 AdjustTokenPrivileges hToken, False, tp, 0, ByVal 0&, ByVal 0& CleanUp: If hToken Then CloseHandle hToken End If End Function Sub main() Dim pID As Long Dim i As Integer Dim strExe As String strExe = "Notepad.Exe" For i = 0 To 4 pID = Shell(strExe, vbNormalFocus) Next i 'Five instances of notepad.exe is now created Debug.Assert False MsgBox "It is " & KillApp(strExe) & " that all instances of " & vbCrLf & strExe & _ " have been terminated!" End Sub 'Another way: Option Explicit Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" _ (ByVal hwnd As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, _ ByVal lParam As Long) As Long Private Const WM_CLOSE = &H10 Private Const WM_QUIT = &H12 Private Target As String Public TargetOpen As Boolean Private Function EnumCallback(ByVal app_hWnd As Long, ByVal param As Long) As Long Dim buf As String * 256 Dim title As String Dim length As Long length = GetWindowText(app_hWnd, buf, Len(buf)) title = Left$(buf, length) If InStr(title, Target) <> 0 Then TargetOpen = True SendMessage app_hWnd, WM_CLOSE, 0, 0 End If EnumCallback = 1 End Function Public Sub TerminateTask(app_name As String, app_exe As String) Dim Process As Variant TargetOpen = False Target = app_name EnumWindows AddressOf EnumCallback, 0 For Each Process In GetObject("winmgmts:").ExecQuery("Select * from Win32_Process " & _ "Where Name = '" & app_exe & "'") TargetOpen = True Process.Terminate Next End Sub 'How can I call this function: 'Call TerminateTask("url.txt","Notepad") 'Another way: 'How to terminate the running process Option Explicit Sub Main() Call TerminateProcess("Notepad.exe") End Sub Public Sub TerminateProcess(app_exe As String) Dim Process As Variant For Each Process In GetObject("winmgmts:").ExecQuery("Select * from Win32_Process " & _ "Where Name = '" & app_exe & "'") Process.Terminate Next End Sub |