Sie übergeben eine Prozess-ID an Funktionen, die einen Fenstergriff übernehmen. Sie möchten Handles für die Fenster der obersten Ebene aufzählen und dann jedes Fenster einer Prozess-ID zuordnen.
Zuerst definieren wir die Ctypes-Funktionsprototypen, um eine korrekte Typprüfung für Funktionsargumente zu erhalten. Verwenden Sie auch use_last_error=True
, um die sicherste Fehlerbehandlung über ctypes.get_last_error
zu erhalten. Viele Windows-Funktionen geben für einen Fehler 0 zurück. Daher ist es praktisch, eine einzige errcheck
-Funktion für diesen Fall zu verwenden, z. B. check_zero
.
from __future__ import print_function
import ctypes
from ctypes import wintypes
from 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
Hier ist eine Funktion, um die sichtbaren Fenster aufzulisten. Es verwendet einen Rückruf, bei dem es sich um einen Abschluss über result
handelt, anstatt das optionale Argument lParam
zu verwenden. Letzteres würde erfordern, das Argument zu werfen. Die Verwendung eines Verschlusses ist einfacher.
def list_windows():
'''Return a 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)
Der Vollständigkeit halber ist hier eine Funktion zum Auflisten aller Prozess-IDs. Dies schließt Prozesse ein, die zu anderen Windows-Sitzungen gehören (z. B. Dienste in Sitzung 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
Zum Beispiel:
if __name__ == '__main__':
print('Process IDs:')
print(*list_pids(), sep='\n')
print('\nWindows:')
print(*list_windows(), sep='\n')
MSDN Links:
Es funktioniert großartig. Danke für Hilfe, Erklärung und Links. – Gunnm