How to get Windows window names with ctypes in python -


i try windows window title names , pids through handles long objects. code works there wrong it. 4 window titles when should 10 or more. can , tell me how fix code? think problem how convert long objects (i don't understand them well, ctypes in general).

from __future__ import print_function ctypes import *  psapi = windll.psapi titles = []   # window title pid def gwtfp():     max_array = c_ulong * 4096     pprocessids = max_array()     pbytesreturned = c_ulong()      psapi.enumprocesses(byref(pprocessids),                         sizeof(pprocessids),                         byref(pbytesreturned))      # number of returned processes     nreturned = pbytesreturned.value/sizeof(c_ulong())     pidprocessarray = [i in pprocessids][:nreturned]     print(pidprocessarray)     #     enumwindows = windll.user32.enumwindows     enumwindowsproc = winfunctype(c_bool, pointer(c_int), pointer(c_int))     getwindowtext = windll.user32.getwindowtextw     getwindowtextlength = windll.user32.getwindowtextlengthw     iswindowvisible = windll.user32.iswindowvisible       process in pidprocessarray:         #print("process pid %d" % process)         if iswindowvisible(process):             length = getwindowtextlength(process)             buff = create_unicode_buffer(length + 1)             getwindowtext(process, buff, length + 1)             titles.append(buff.value)   gwtfp() print(titles) 

you're passing process id functions take window handle. want enumerate handles top-level windows , map each window process id.

first lets define ctypes function prototypes proper type checking on function arguments. also, use use_last_error=true safest error handling via ctypes.get_last_error. lot of windows functions return 0 error, it's convenient have single errcheck function case, such check_zero.

from __future__ import print_function  import ctypes ctypes import wintypes collections import namedtuple  user32 = ctypes.windll('user32', use_last_error=true)  def check_zero(result, func, args):         if not result:         err = ctypes.get_last_error()         if err:             raise ctypes.winerror(err)     return args  if not hasattr(wintypes, 'lpdword'): # py2     wintypes.lpdword = ctypes.pointer(wintypes.dword)  windowinfo = namedtuple('windowinfo', 'pid title')  wndenumproc = ctypes.winfunctype(     wintypes.bool,     wintypes.hwnd,    # _in_ hwnd     wintypes.lparam,) # _in_ lparam  user32.enumwindows.errcheck = check_zero user32.enumwindows.argtypes = (    wndenumproc,      # _in_ lpenumfunc    wintypes.lparam,) # _in_ lparam  user32.iswindowvisible.argtypes = (     wintypes.hwnd,) # _in_ hwnd  user32.getwindowthreadprocessid.restype = wintypes.dword user32.getwindowthreadprocessid.argtypes = (   wintypes.hwnd,     # _in_      hwnd   wintypes.lpdword,) # _out_opt_ lpdwprocessid  user32.getwindowtextlengthw.errcheck = check_zero user32.getwindowtextlengthw.argtypes = (    wintypes.hwnd,) # _in_ hwnd  user32.getwindowtextw.errcheck = check_zero user32.getwindowtextw.argtypes = (     wintypes.hwnd,   # _in_  hwnd     wintypes.lpwstr, # _out_ lpstring     ctypes.c_int,)   # _in_  nmaxcount 

here's function list visible windows. uses callback that's closure on result instead of using optional lparam argument. latter require casting argument. using closure simpler.

def list_windows():     '''return sorted list of visible windows.'''     result = []     @wndenumproc     def enum_proc(hwnd, lparam):         if user32.iswindowvisible(hwnd):             pid = wintypes.dword()             tid = user32.getwindowthreadprocessid(                         hwnd, ctypes.byref(pid))             length = user32.getwindowtextlengthw(hwnd) + 1             title = ctypes.create_unicode_buffer(length)             user32.getwindowtextw(hwnd, title, length)             result.append(windowinfo(pid.value, title.value))         return true     user32.enumwindows(enum_proc, 0)     return sorted(result) 

for completeness, here's function list process ids. includes processes belong other windows sessions (e.g. services in session 0).

psapi = ctypes.windll('psapi', use_last_error=true)  psapi.enumprocesses.errcheck = check_zero psapi.enumprocesses.argtypes = (    wintypes.lpdword,  # _out_ pprocessids    wintypes.dword,    # _in_  cb    wintypes.lpdword,) # _out_ pbytesreturned  def list_pids():     '''return sorted list of process ids.'''     length = 4096     pid_size = ctypes.sizeof(wintypes.dword)     while true:         pids = (wintypes.dword * length)()         cb = ctypes.sizeof(pids)         cbret = wintypes.dword()         psapi.enumprocesses(pids, cb, ctypes.byref(cbret))         if cbret.value < cb:             length = cbret.value // pid_size             return sorted(pids[:length])         length *= 2 

for example:

if __name__ == '__main__':     print('process ids:')     print(*list_pids(), sep='\n')     print('\nwindows:')     print(*list_windows(), sep='\n') 

msdn links:


Comments

Popular posts from this blog

ios - RestKit 0.20 — CoreData: error: Failed to call designated initializer on NSManagedObject class (again) -

java - Digest auth with Spring Security using javaconfig -

laravel - PDOException in Connector.php line 55: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) -