我试图让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()什么都不做。
其他测试
我尝试了this answer中的代码,它运行正常。但是这段代码 还有其他一些问题。
SendInput() returns '0',表示“被其他人阻止 线程“
调用ctypes.GetLastError()会给我们error code 87,意思是“ERROR_INVALID_PARAMETER”
在这里,我们陷入困境,因为我的Windows编程非常有限,任何人都可以对此有所了解吗?
编辑1:
答案 0 :(得分:0)
您正在使用的Structure
和Union
类有两个问题。我将使用其中一个类重现the code you linked to的代码段:
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
,结构将会错位并且大小错误。
第二个问题是ULONG_PTR
中有没有ctypes.wintypes
,这将是dwExtraInfo
<的正确的数据类型/ strong>即可。在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
使用DWORD
或ULONG
用于dwExtraInfo
因此只能在32位Windows下工作,否则会产生错误的大小。
虽然使用一些基于POINTER
的数据类型会恰好产生正确对齐和大小的结构,但在意义和使用方面都是错误的,因为ULONG_PTR
是&#34;无符号整数,也可以存储(铸造)指针&#34;而不是一个实际的指针。
通过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),
]