【问题标题】:How can I debug SendKeysCtypes on (win7 64bit, py2.7) further?如何进一步调试(win7 64bit,py2.7)上的 SendKeysCtypes?
【发布时间】:2012-05-08 17:08:46
【问题描述】:

我正在尝试让 SendKeysCtypes 在 py2.7 和 win7 64bit 上工作。 Here is src

问题:

运行SendKeysCtypes.py,没有任何反应。测试应该打开记事本并写一些文本。

问题代码是这样的:

def GetInput(self):
    "Build the INPUT structure for the action"
    actions = 1
    # if both up and down
    if self.up and self.down:
        actions = 2

    inputs = (INPUT * actions)()

    vk, scan, flags = self._get_key_info()

    for inp in inputs:
        inp.type = INPUT_KEYBOARD

        inp._.ki.wVk = vk
        inp._.ki.wScan = scan
        inp._.ki.dwFlags |= flags

    # if we are releasing - then let it up
    if self.up:
        inputs[-1]._.ki.dwFlags |= KEYEVENTF_KEYUP

    return inputs

def Run(self):
    "Execute the action"
    inputs = self.GetInput()
    return SendInput(
        len(inputs),
        ctypes.byref(inputs),
        ctypes.sizeof(INPUT))

上面代码中的SendInput() 什么都不做。

其他测试

在这里我们被卡住了,因为我的 Windows 编程非常有限,有人能解释一下吗?

编辑 1:

  • 按照“64 位问题”跟踪,将我带到这个SO question,看看我是否可以转换它。

【问题讨论】:

    标签: python windows 64-bit pywin32 sendkeys


    【解决方案1】:

    您正在使用的StructureUnion 类存在两个问题。我将从the code you linked to 复制一个 sn-p,其中一个类作为示例:

    class KEYBDINPUT(ctypes.Structure):
        "A particular keyboard event"
        _pack_ = 2  # FIXME: don't do this
        _fields_ = [
            # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4292
            ('wVk', WORD),
            ('wScan', WORD),
            ('dwFlags', DWORD),
            ('time', DWORD),
            ('dwExtraInfo', DWORD),  # FIXME: use correct data type
        ]
    

    FIXME是我添加的以指出有问题的部分。)

    首先是您使用的是_pack_ = 2,这不正确。您根本不应该使用任何 _pack_ 对齐说明符。默认值在 32 位和 64 位 Windows 上都可以正常工作。

    它在 32 位 Windows 上与 _pack_ = 2 一起工作纯属偶然:代码中使用的所有 2 字节大小的数据类型都是成对出现的,并且从已经对齐的边界开始,因此恰好产生与4 字节对齐。

    但是,在 64 位 Windows 下,基本对齐方式是 8 字节,因此如果您在其中使用 _pack_ = 2_pack_ = 4,结构会错位且大小错误。

    第二个问题是ctypes.wintypes没有ULONG_PTR,这将是dwExtraInfo正确数据类型。在 32 位 Windows 下ULONG_PTR 是一个无符号 32 位整数,而在 64 位 Windows 下它是一个无符号 64 位整数。

    MSDN article about Windows Data Types 显示了它是如何定义的:

    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    

    DWORDULONG 用于dwExtraInfo 因此只能在32 位Windows 下工作,否则会产生错误的大小。

    虽然使用一些基于 POINTER 的数据类型会碰巧产生正确对齐和大小的结构,但它在含义和用法上都是错误的,因为 ULONG_PTR 是“一个无符号整数,它也可以存储一个(强制转换的)指针”而不是一个实际的指针。

    查看wintypes,您会注意到WPARAM 的定义恰好与ULONG_PTR 的定义完全相同。因此,获得ULONG_PTR 的一种快速而肮脏(但仍然相当稳健)的方法是:

    from ctypes.wintypes import WPARAM as ULONG_PTR
    

    或者,您可以使用受他们启发的一段代码并自己定义:

    import ctypes
    
    for ULONG_PTR in [ctypes.c_ulong, ctypes.c_ulonglong]:
        if ctypes.sizeof(ULONG_PTR) == ctypes.sizeof(ctypes.c_void_p):
            break
    else:
        raise TypeError("cannot find a suitable type for ULONG_PTR")
    

    有了这些适应,您可以像这样定义结构:

    class MOUSEINPUT(ctypes.Structure):
        _fields_ = [
            ('dw',          LONG),
            ('dy',          LONG),
            ('mouseData',   DWORD),
            ('dwFlags',     DWORD),
            ('time',        DWORD),
            ('dwExtraInfo', ULONG_PTR),
        ]
    
    
    class KEYBDINPUT(ctypes.Structure):
        _fields_ = [
            ('wVk',         WORD),
            ('wScan',       WORD),
            ('dwFlags',     DWORD),
            ('time',        DWORD),
            ('dwExtraInfo', ULONG_PTR),
        ]
    
    
    class HARDWAREINPUT(ctypes.Structure):
        _fields_ = [
            ('uMsg',    DWORD),
            ('wParamL', WORD),
            ('wParamH', WORD),
        ]
    
    
    class _INPUT(ctypes.Union):
        _fields_ = [
            ('mi', MOUSEINPUT),
            ('ki', KEYBDINPUT),
            ('hi', HARDWAREINPUT),
        ]
    
    
    class INPUT(ctypes.Structure):
        _anonymous_ = ['']
        _fields_ = [
            ('type', DWORD),
            ('', _INPUT),
        ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多