Obtenga el título de una ventana de otro progtwig usando el nombre del proceso

Esta pregunta es probablemente bastante básica, pero estoy teniendo dificultades para resolverla. Supongo que tendré que usar algo en ctypes.windll.user32 . Tenga en cuenta que tengo poca o ninguna experiencia en el uso de estas bibliotecas o incluso de los ctypes en general.

He usado este código para enumerar todos los títulos de las ventanas, pero no tengo idea de cómo se supone que debo cambiar este código para obtener un título de ventana con un nombre de proceso:

 import ctypes EnumWindows = ctypes.windll.user32.EnumWindows EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) GetWindowText = ctypes.windll.user32.GetWindowTextW GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW IsWindowVisible = ctypes.windll.user32.IsWindowVisible titles = [] def foreach_window(hwnd, lParam): if IsWindowVisible(hwnd): length = GetWindowTextLength(hwnd) buff = ctypes.create_unicode_buffer(length + 1) GetWindowText(hwnd, buff, length + 1) titles.append(buff.value) return True EnumWindows(EnumWindowsProc(foreach_window), 0) print(titles) 

Este código es de https://sjohannes.wordpress.com/2012/03/23/win32-python-getting-all-window-titles/

Si mi pregunta no está clara, me gustaría lograr algo como esto (solo un ejemplo, no estoy preguntando específicamente sobre Spotify):

 getTitleOfWindowbyProcessName("spotify.exe") // returns "Avicii - Waiting For Love" (or whatever the title is) 

Una complicación que puede surgir si hay varias ventanas ejecutándose con el mismo nombre de proceso (por ejemplo, múltiples ventanas de cromo)

Gracias.


EDITAR : Para aclarar, quiero un código que tome un nombre de proceso y devuelva una lista (posiblemente vacía) de títulos de ventanas que ese proceso posee como cadenas.

Esto es lo que quise decir en el comentario:

 import win32gui def enumWindowsProc(hwnd, lParam): print win32gui.GetWindowText(hwnd) win32gui.EnumWindows(enumWindowsProc, 0) 

A continuación, pegué todo … no funciona en la PC en la que estoy ahora, ya que me equivoqué con la configuración de seguridad (¡es un XP !) Y obtengo un montón de Acceso denegado (error código: 5 ) errores, pero aquí está.

code.py :

 #!/usr/bin/env python3 import sys import os import traceback import ctypes from ctypes import wintypes import win32con import win32api import win32gui import win32process def enumWindowsProc(hwnd, lParam): if (lParam is None) or ((lParam is not None) and (win32process.GetWindowThreadProcessId(hwnd)[1] == lParam)): text = win32gui.GetWindowText(hwnd) if text: wStyle = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE) if wStyle & win32con.WS_VISIBLE: print("%08X - %s" % (hwnd, text)) def enumProcWnds(pid=None): win32gui.EnumWindows(enumWindowsProc, pid) def enumProcs(procName=None): pids = win32process.EnumProcesses() if procName is not None: bufLen = 0x100 _OpenProcess = ctypes.cdll.kernel32.OpenProcess _OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD] _OpenProcess.restype = wintypes.HANDLE _GetProcessImageFileName = ctypes.cdll.psapi.GetProcessImageFileNameA _GetProcessImageFileName.argtypes = [wintypes.HANDLE, wintypes.LPSTR, wintypes.DWORD] _GetProcessImageFileName.restype = wintypes.DWORD _CloseHandle = ctypes.cdll.kernel32.CloseHandle _CloseHandle.argtypes = [wintypes.HANDLE] _CloseHandle.restype = wintypes.BOOL filteredPids = () for pid in pids: try: hProc = _OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, pid) except: print("Process [%d] couldn't be opened: %s" % (pid, traceback.format_exc())) continue try: buf = ctypes.create_string_buffer(bufLen) _GetProcessImageFileName(hProc, buf, bufLen) if buf.value: name = buf.value.decode().split(os.path.sep)[-1] #print name else: _CloseHandle(hProc) continue except: print("Error getting process name: %s" % traceback.format_exc()) _CloseHandle(hProc) continue if name.lower() == procName.lower(): filteredPids += (pid,) return filteredPids else: return pids def main(args): if args: procName = args[0] else: procName = None pids = enumProcs(procName) #print(pids) for pid in pids: enumProcWnds(pid) if __name__ == "__main__": print("Python {:s} on {:s}\n".format(sys.version, sys.platform)) main(sys.argv[1:]) 

No hace falta decir que:

  • Para que este código funcione, debe ejecutarlo como un usuario privilegiado ( Administrador ); se requiere al menos SeDebugPrivilege ( [MS.Docs]: Constantes de privilegios ).
  • Puede haber sorpresas cuando los procesos se ejecutan en modos de 32/64 bits (el proceso de Python desde el que se ejecuta este código y los procesos de destino enumerados por el código)