Welcome, guest | Sign In | My Account | Store | Cart

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, 56 lines
 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()

7 comments

Gordon Hennesy 19 years, 6 months ago  # | flag

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

Eric Koome (author) 19 years, 6 months ago  # | flag

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

Jonathan Kolyer 18 years, 6 months ago  # | flag

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)
Wolfgang Eichler 16 years, 1 month ago  # | flag

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 ...
Jamie Murray 14 years, 5 months ago  # | flag

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.

Jamie Murray 14 years, 5 months ago  # | flag

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.

anatoly techtonik 13 years, 9 months ago  # | flag

According to recipe header license tag need update from PSF to GPL.

Created by Eric Koome on Tue, 14 Sep 2004 (PSF)
Python recipes (4591)
Eric Koome's recipes (3)

Required Modules

Other Information and Tasks