【问题标题】:Python ctypes EnumThreadWindows failing with error 87 (ERROR_INVALID_PARAMETER)Python ctypes EnumThreadWindows 失败并出现错误 87 (ERROR_INVALID_PARAMETER)
【发布时间】:2021-05-27 01:00:25
【问题描述】:

我似乎无法让 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) 无济于事。 我做错了什么?

【问题讨论】:

  • pid.value,看起来您传递的是进程 ID,而不是 document 中的线程 ID。
  • 哦,哈哈。哎呀。谢谢,@Drake Wu。

标签: python-3.x windows winapi ctypes


【解决方案1】:

这是工作代码。确保传递有效的线程 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')

【讨论】:

  • 感谢@Mark Tolonen 的回复和代码。我有很多东西要学(对编码很陌生)。您是如何获得线程 ID 的?
猜你喜欢
  • 2020-07-06
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-24
相关资源
最近更新 更多