¿Utiliza Python para enviar pulsaciones de teclas a juegos en Windows?

He estado trabajando con Python en un entorno de Windows y escribí un script para automatizar algunas tareas en un juego conocido. La tarea implica un uso intensivo de las entradas del mouse y del teclado.

Dicho script, sin embargo, solo tiene un problema: no puede enviar pulsaciones de teclas a la aplicación. He probado al menos 3 métodos diferentes que publicaré a continuación y algunas variaciones (también leí décimas de preguntas / respuestas similares, sin resultado)

Primero, usando elwin32api módulo:

f = 0x46 # VirtualKey Code of the letter "F", see http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx 

win32api.keybd_event(f,0,0,0) # holds the "F" key down
time.sleep(2) # waits 2 seconds
win32api.keybd_event(f,0,win32con.KEYEVENTF_KEYUP,0) # releases the key

No tiene nada de especial, funciona perfectamente (se escribe una "f") en cualquier editor de texto, navegador ... Sin embargo, si abro un juego como, por ejemplo, Counter-Strike, la pulsación de tecla se "pierde", como en no ocurre nada Por otro lado, si abro la consola de Counter-Strike, entonces la pulsación de teclaconsigue registrado (como en el bloc de notas). Probado en otro juego, League of Legends, exactamente el mismo comportamiento. En el juego real, no se detecta ninguna pulsación de tecla. Sin embargo, si abro el chat (aúnEn el juego) y vuelva a ejecutar el script, luego el chat lo registra.

Sobre el segundo método:

shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys("F")

Exactamente el mismo comportamiento que el anterior. Funciona bien en todo menos en el juego, y solo funciona en chats.

Tercer método (el crédito va a quien lo haya publicado en otro hilo de stackoverflow), más avanzado (llamandoSendInput()) con elctypes módulo. En teoría, de los tres, este es el más cercano para simular una pulsación de tecla física real:

SendInput = ctypes.windll.user32.SendInput

# C struct redefinitions 
PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
    _fields_ = [("wVk", ctypes.c_ushort),
                ("wScan", ctypes.c_ushort),
                ("dwFlags", ctypes.c_ulong),
                ("time", ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class HardwareInput(ctypes.Structure):
    _fields_ = [("uMsg", ctypes.c_ulong),
                ("wParamL", ctypes.c_short),
                ("wParamH", ctypes.c_ushort)]

class MouseInput(ctypes.Structure):
    _fields_ = [("dx", ctypes.c_long),
                ("dy", ctypes.c_long),
                ("mouseData", ctypes.c_ulong),
                ("dwFlags", ctypes.c_ulong),
                ("time",ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class Input_I(ctypes.Union):
    _fields_ = [("ki", KeyBdInput),
                 ("mi", MouseInput),
                 ("hi", HardwareInput)]

class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("ii", Input_I)]

# Actuals Functions

def PressKey(hexKeyCode):

    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( hexKeyCode, 0x48, 0, 0, ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def ReleaseKey(hexKeyCode):

    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( hexKeyCode, 0x48, 0x0002, 0, ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))


def KeyPress():
    PressKey(0x46) # press F
    time.sleep(.5)
    ReleaseKey(0x46) #release F

... tampoco funciona. Por extraño que parezca, muestra elexacto mismo comportamiento que los tres anteriores: funciona en cualquier editor de texto / aplicación simple, los juegos lo ignoran o solo se registra en la sección de chat del juego.

Si tuviera que adivinar, diría que estos juegos obtienen sus eventos de teclado de alguna otra manera que no he cubierto con ninguno de estos 3 métodos, ignorando así estos.

Agradecería cualquier ayuda. Si es posible, con ejemplos concretos de código que funcionan en CS, LoL o juegos similares para que tenga un punto de partida.

Respuestas a la pregunta(2)

Su respuesta a la pregunta