首页 > 解决方案 > Python ctypes EnumThreadWindows 失败并出现错误 87 (ERROR_INVALID_PARAMETER)

问题描述

我似乎无法让 EnumThreadWindows 工作。它一直失败并出现错误 87。代码:

error = ctypes.WinDLL('Kernel32').GetLastError
enum_func = ctypes.WINFUNCTYPE(wintypes.BOOL,
                               wintypes.HWND,
                               wintypes.LPARAM)

def callback(hwnd, lParam):
    length = ctypes.WinDLL('User32').GetWindowTextLengthW(hwnd) + 1
    buf = ctypes.create_unicode_buffer(length)
    ctypes.WinDLL('User32').GetWindowTextW(hwnd, buf, length)
    print(buf.value)

worker = enum_func(callback)
test = ctypes.WinDLL('User32').EnumThreadWindows(6000, worker, None)
print(error(test))

我试过了pid = wintypes.DWORD(6000)test = ctypes.WinDLL('User32').EnumThreadWindows(pid.value, worker, None)没有用。我究竟做错了什么?

标签: python-3.xwindowswinapictypes

解决方案


这是工作代码。确保传递有效的线程 ID。

您可能对 LPARAM 可以是任何东西(包括 Python 对象)感兴趣,因此如果您传递 Python 对象,则可以在回调中对其进行操作:

import ctypes
from ctypes import wintypes
from collections import namedtuple

Window = namedtuple('Window','hwnd title')

WNDENUMPROC = ctypes.WINFUNCTYPE(wintypes.BOOL,
                                 wintypes.HWND,
                                 ctypes.py_object) # to allow any Python object.

u32 = ctypes.WinDLL('user32',use_last_error=True) # to ensure GetLastError was captured

# Declaring arguments and return type helps catch errors and support 64-bit.
# HWND is 64-bit on 64-bit Python, and could get truncated if left to ctypes default
# of c_int (32-bit).  This code works on Python 2.7 and 3.9.
u32.GetWindowTextLengthW.argtypes = wintypes.HWND,
u32.GetWindowTextLengthW.restype = ctypes.c_int
u32.GetWindowTextW.argtypes = wintypes.HWND,wintypes.LPWSTR,ctypes.c_int
u32.GetWindowTextW.restype = ctypes.c_int
u32.EnumThreadWindows.argtypes = wintypes.DWORD,WNDENUMPROC,ctypes.py_object # to pass Python object
u32.EnumThreadWindows.restype = wintypes.BOOL

@WNDENUMPROC # decorator makes this a ctypes-compatible function
def callback(hwnd, lParam):
    length = u32.GetWindowTextLengthW(hwnd) + 1
    buf = ctypes.create_unicode_buffer(length)
    u32.GetWindowTextW(hwnd, buf, length)
    lParam.append(Window(hwnd,buf.value)) # append data to the callback parameter
    return True # return True to continue enumeration

result = [] # A python object
if u32.EnumThreadWindows(6332, callback, result): # 6332 was a thread in my explore.exe
    for wnd in result:  # list results when enumeration complete
        print(wnd)
else:
    print('error:',ctypes.get_last_error()) # print error of EnumThreadWindows.
                                            # Python could use a Win32 function that fails in
                                            # between the ctypes call and calling GetLastError
                                            # directly.

输出:

Window(hwnd=65832, title='')
Window(hwnd=65838, title='')
Window(hwnd=131174, title='')
Window(hwnd=65682, title='')
Window(hwnd=65678, title='')
Window(hwnd=65826, title='Program Manager')
Window(hwnd=196928, title='MSCTFIME UI')
Window(hwnd=65680, title='Default IME')

推荐阅读