Tuesday, December 30, 2014

Enumerate and Kill Selected Windows Processess


A question inside Foxite was raised yesterday requesting for a way to kill selected Windows processeses using API calls as what we normally use is the scripting way.  And googling around, there are ways shown by several developers; but none, AFAIK, that terminates successfully a process on each run/attempt.  

My first attempt yesterday combining information I gleamed across the web from several developers were not able to close the target process on every run.  Digging further, one fault I see is my usage of GetModuleFileNameEx is failing to get a proper result thus skipping onto the next process among processes list.  

With the belief that everything is possible given enough time and attention, when I arrived back in the office this morning, I renewed experimenting on the task; playing with different values and finally I settled with dwDesiredAccess value of 1041 here for the OpenProcess API call as this gets the proper handle necessary later on terminating my target process, though it skips some vital OS processes.

For whatever reason, said value of 1041 also gets more result than the PROCESS_ALL_ACCESS value which I expected to give more result.  Maybe in the future I will play further with this, or maybe not anymore.

I included in this function a cursor showing the remaining processes it was able to acquire showing the Process Name and ID.  This is optional as in reality we do not need this unless out of maybe a curiosity?  Here are the codes:

KillProcessAPI('winrar.exe')

***********
Procedure KillProcessAPI(cAppName)
***********
Local lnLoop, lnBytesReturned, lnPID, lnPH, lcBuffer, lnSize
* This is just so we can see the processess in task manager
Create Cursor junk (pname c(40), pid i)
Index On pname Tag pname

Clear
cAppName = Upper(Alltrim(m.cAppName))

Declare Integer EnumProcesses In psapi.Dll ;
      String  @lpidProcess,;
      Integer cb,;
      Integer @cbNeeded

Declare Integer OpenProcess In win32api  ;
      Integer dwDesiredAccess,;
      Integer bInheritHandle,;
      Integer dwProcessId

Declare Integer GetModuleFileNameEx In psapi;
      INTEGER hProcess,;
      INTEGER hModule,;
      STRING ModuleName,;
      INTEGER nSize

Declare Integer CloseHandle In win32api ;
      Integer hObject

Declare Long GetExitCodeProcess In kernel32 Long, Long @

Declare TerminateProcess In WIN32API ;
      INTEGER hProcess, ;
      INTEGER fuExitCode

lnSize = 4096 * 4
lnBytesReturned = 0
lcBuffer = Replicate(Chr(0), m.lnSize)
lnResult = EnumProcesses(@lcBuffer,m.lnSize,@lnBytesReturned)

If  m.lnResult <> 0
      For lnLoop = 1 To lnBytesReturned / 4
            lnPID = BUF2DWORD(Substr (m.lcBuffer, 4 * (m.lnLoop - 1) + 1, 4))
            lnPH = OpenProcess(1041, 0, m.lnPID)
            If lnPH <> 0
                  lnResult = GetModuleFileNameEx(lnPH, 0,@lcBuffer, 255)
                  lcPN = Alltrim(Upper(Justfname(Strtran(Left(m.lcBuffer, m.lnResult), "\??\", ""))))
                  If !Empty(m.lcPN)
                        Insert Into junk Values (m.lcPN,m.lnPID)
                  ENDIF
                  IF m.cAppName = m.lcPN
                        * Terminate target
                        lnExitCode = 0
                        GetExitCodeProcess(m.lnPH, @lnExitCode)
                        TerminateProcess(m.lnPH,m.lnExitCode)
                  Endif
                  CloseHandle(lnPH)
            Endif
      Next
Endif
* Show the list of processes it was able to enumerate
Browse Normal
Clear DLLs
Endproc

**********
Function BUF2DWORD(cBuffer)
**********
Return Asc(Substr(m.cBuffer, 1.1)) +;
      ASC(Substr(m.cBuffer, 2.1)) * 256 +;
      ASC(Substr(m.cBuffer, 3.1 )) * 65536 +;
      ASC(Substr(m.cBuffer, 4.1)) * 16777216


Hope this helps as well! Cheers!

No comments:

Post a Comment