ActiveState Code

Recipe 305279: getting process information on windows


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

Python
 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()

Comments

  1. 1. At 11:15 a.m. on 16 sep 2004, Gordon Hennesy said:

    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:

    modname = c_buffer(260)
    

    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

  2. 2. At 12:47 a.m. on 22 sep 2004, Eric Koome (the author) said:

    Thanks Gordon. Fixed the bug by cleaning up the contents of modname variable

  3. 3. At 4:36 p.m. on 27 sep 2005, Jonathan Kolyer said:

    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):

    import win32api, win32con, win32security
    from ntsecuritycon import TokenUser
    appname = 'Name of target application'
    currentUserName = None
    
    ...
    
    if appname==procName:
        if not currentUserName:
            tok = win32security.OpenProcessToken(win32api.GetCurrentProcess(),
                                                 win32con.TOKEN_QUERY)
            sid, attr = win32security.GetTokenInformation(tok, TokenUser)
            win32api.CloseHandle(tok)
            currentUserName, dom, typ = win32security.LookupAccountSid(None, sid)
    
        hToken = win32security.OpenProcessToken(hProcess, win32con.TOKEN_QUERY)
        if hToken:
            sidObj, intVal = win32security.GetTokenInformation(hToken, TokenUser)
            if sidObj:
                accountName, domainName, accountTypeInt = win32security.LookupAccountSid(None, sidObj)
                if accountName==currentUserName:
                    print 'accountname=%s'%accountName
                else: print 'NOT current user'
            win32api.CloseHandle(hToken)
    
  4. 4. At 9:01 a.m. on 7 feb 2008, Wolfgang Eichler said:

    minor improvements. 1. I use: pids = win32process.EnumProcesses()

    to get a complete list of PIDs (not limited by arr = c_ulong * 256)

    1. to convert the buffer modname to python string I use:

    string_at(modname) (from ctypes); this makes the clean up obsolete

    1. Anyway many thanks for your usefull example code ...
  5. 5. At 5:11 a.m. on 7 oct 2009, James Murray said:

    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.

  6. 6. At 6:59 a.m. on 7 oct 2009, James Murray said:

    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.

Sign in to comment