【问题标题】:Enumerating windows trough ctypes in python在python中通过ctypes枚举windows
【发布时间】:2014-01-17 00:51:43
【问题描述】:

我正在尝试在 Python3.3 中使用 ctypes 获取所有可见窗口的列表

但是使用我拥有的代码,不会返回一个窗口。 EnumWindows函数失败,返回错误码为0。

import ctypes

user32 = ctypes.windll.user32

def worker(hwnd, lParam):
    length = user32.GetWindowTextLengthW(hwnd) + 1
    buffer = ctypes.create_unicode_buffer(length)
    user32.GetWindowTextW(hwnd, buffer, length)
    print("Buff: ", repr(buffer.value))

a = ctypes.WINFUNCTYPE(ctypes.c_bool,
                       ctypes.POINTER(ctypes.c_int),
                       ctypes.POINTER(ctypes.c_int))(worker)

if not user32.EnumWindows(a, True):
    print("Err: ", ctypes.windll.kernel32.GetLastError())

这是当前的输出:

Buff:  ''
Err:  0

这是我所期望的:

Buff: 'Python 3.3.2 shell'
Buff: 'test.py - C:\Users\...'
[...]

您能指出我实现这一目标的正确方向吗?提前致谢。

【问题讨论】:

    标签: python winapi ctypes


    【解决方案1】:

    回调需要返回TRUE才能继续枚举。您的回调隐式返回None,这是错误的。以下修订版应该可以满足您的要求:

    import ctypes
    from ctypes import wintypes
    
    WNDENUMPROC = ctypes.WINFUNCTYPE(wintypes.BOOL,
                                     wintypes.HWND,
                                     wintypes.LPARAM)
    user32 = ctypes.windll.user32
    user32.EnumWindows.argtypes = [
        WNDENUMPROC,
        wintypes.LPARAM]
    user32.GetWindowTextLengthW.argtypes = [
        wintypes.HWND]
    user32.GetWindowTextW.argtypes = [
        wintypes.HWND,
        wintypes.LPWSTR,
        ctypes.c_int]
    
    def worker(hwnd, lParam):
        length = user32.GetWindowTextLengthW(hwnd) + 1
        buffer = ctypes.create_unicode_buffer(length)
        user32.GetWindowTextW(hwnd, buffer, length)
        print("Buff: ", repr(buffer.value))
        return True
    
    cb_worker = WNDENUMPROC(worker)
    if not user32.EnumWindows(cb_worker, 42):
        raise ctypes.WinError()
    

    HWND 句柄类型是c_void_p 的别名。 LPARAM 是一个与指针存储大小相同的整数。在wintypes中定义如下:

    if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
        WPARAM = ctypes.c_ulong
        LPARAM = ctypes.c_long
    elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
        WPARAM = ctypes.c_ulonglong
        LPARAM = ctypes.c_longlong
    

    【讨论】:

    • .argtypes 总是必要的吗?或者你把它们展示给函数采用什么类型?
    • @gcq:它们不是绝对必要的,但它们非常有用,因为它们可以在调用被发送到 C 领域的危险之前对类型兼容性进行健全性检查,对于某些类型,它们也启用将传递的参数自动转换为正确的类型。收益远远超过成本(在代码中多增加一行)。
    猜你喜欢
    • 2020-08-24
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2019-01-28
    相关资源
    最近更新 更多