This recipe will enumerate active processes as seen under windows Task Manager on Win NT/2k/XP using PSAPI.dll (new api for processes) and using ctypes. Use it as you please
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 | """
Enumerates active processes as seen under windows Task Manager on Win NT/2k/XP using PSAPI.dll
(new api for processes) and using ctypes.Use it as you please.
Based on information from http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q175030&ID=KB;EN-US;Q175030
By Eric Koome
email ekoome@yahoo.com
license GPL
"""
from ctypes import *
#PSAPI.DLL
psapi = windll.psapi
#Kernel32.DLL
kernel = windll.kernel32
def EnumProcesses():
arr = c_ulong * 256
lpidProcess= arr()
cb = sizeof(lpidProcess)
cbNeeded = c_ulong()
hModule = c_ulong()
count = c_ulong()
modname = c_buffer(30)
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010
#Call Enumprocesses to get hold of process id's
psapi.EnumProcesses(byref(lpidProcess),
cb,
byref(cbNeeded))
#Number of processes returned
nReturned = cbNeeded.value/sizeof(c_ulong())
pidProcess = [i for i in lpidProcess][:nReturned]
for pid in pidProcess:
#Get handle to the process based on PID
hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
False, pid)
if hProcess:
psapi.EnumProcessModules(hProcess, byref(hModule), sizeof(hModule), byref(count))
psapi.GetModuleBaseNameA(hProcess, hModule.value, modname, sizeof(modname))
print "".join([ i for i in modname if i != '\x00'])
#-- Clean up
for i in range(modname._length_):
modname[i]='\x00'
kernel.CloseHandle(hProcess)
if __name__ == '__main__':
EnumProcesses()
|
modname not getting cleared. Eric, great admin tool! I seemed to have a problem: if a modname was shorter than one earlier in the list, it left part of the name behind. I'm running XP, if that makes a difference. My quick and dirty fix is to copy the line:
between the psapi.EnumProcessModules and the psapi.GetModuleBaseNameA lines. This is possibly overkill, creating a new c_buffer, but on a single machine, it's hard to run enough processes to make this noticeable.
Cheers,
Gordon Hennesy
Thanks Gordon. Fixed the bug by cleaning up the contents of modname variable
Need user name, process name. I need to match both user name and process name to correctly identify the process I'm interested in, so I've added this snippet of code (called when the process name is the targetted process):
minor improvements. 1. I use: pids = win32process.EnumProcesses()
to get a complete list of PIDs (not limited by arr = c_ulong * 256)
string_at(modname) (from ctypes); this makes the clean up obsolete
Note: This (maybe not surprisingly) doesn't return any of the x64 processes running on an x64 build of windows. Looking into this just now.
http://msdn.microsoft.com/en-us/library/ms683198%28VS.85%29.aspx explains the limitations found by some. Made a MS tasklist commandline return into a var and marry up any empty task names with their task ids and insert the output from the OS cmd line's variable for the process name.
PIDs for these x64 processes do get returned but modname returns an empty value sadly, thus the above workaround.
According to recipe header license tag need update from PSF to GPL.