2011-07-26 11 views
10

A continuación se muestra un extracto de algún código que estoy usando para simular pulsaciones de teclas a través de SendInput API. Esto funciona correctamente si configuro mi aplicación para compilar para una CPU x86, pero no funciona para la compilación de la CPU x64.SendInput y 64bits

Supongo que tiene algo que ver con el hecho de que x64 usa punteros de tamaño doble, pero traté de cambiar este [FieldOffset(4)] a este [FieldOffset(8)] pero no funcionó.

¿Podría ser algo relacionado con el hecho de que está importando la versión de 32 bits de user32.dll?

#region SendInput API 

    [DllImport("user32.dll", EntryPoint = "SendInput", SetLastError = true)] 
    static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); 

    [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)] 
    static extern IntPtr GetMessageExtraInfo(); 

    private enum KeyEvent 
    { 
     KeyUp = 0x0002, 
     KeyDown = 0x0000, 
     ExtendedKey = 0x0001 
    } 

    private struct KEYBDINPUT 
    { 
     public ushort wVk; 
     public ushort wScan; 
     public uint dwFlags; 
     public long time; 
     public uint dwExtraInfo; 
    }; 

    [StructLayout(LayoutKind.Explicit, Size = 28)] 
    private struct INPUT 
    { 
     [FieldOffset(0)] 
     public uint type; 
     [FieldOffset(4)] 
     public KEYBDINPUT ki; 
    }; 

    #endregion 

    public void sendKey(KeyCode Key) 
    { 
     INPUT[] InputList = new INPUT[2]; 

     INPUT keyInput = new INPUT(); 
     keyInput.type = 1; 

     keyInput.ki.wScan = 0; 
     keyInput.ki.time = 0; 
     keyInput.ki.dwFlags = (int)KeyEvent.KeyDown; 
     keyInput.ki.dwExtraInfo = (uint)GetMessageExtraInfo(); 
     keyInput.ki.wVk = (ushort)Key; 

     InputList[0] = keyInput; 

     keyInput.ki.dwFlags = (int)KeyEvent.KeyUp; 

     InputList[1] = keyInput; 

     SendInput((uint)2, InputList, Marshal.SizeOf(InputList[0])); 
    } 
+1

De algún modo, algo de código que faltaba por lo que la línea en cuestión deberá leer '[StructLayout (LayoutKind.Explicit, Tamaño = 28)]' – Cheetah

Respuesta

11

En relación con el error que SLaks identificados, el problema que queda es que el tamaño de INPUT es incorrecta. Esto significa que SendInput falla dado que recibe un parámetro del tipo INPUT[]. No puede especificar el tamaño con StructLayout(LayoutKind.Explicit, Size = 28) ya que quiere un código que maneje tanto x86 como x64.

Todo esto se debe al hecho de que solo ha incluido la estructura KEYBRDINPUT en INPUT. La estructura MOUSEINPUT es mayor que KEYBRDINPUT, que es la causa de su problema.

La mejor solución es definir la estructura de ENTRADA correctamente, incluida la parte de unión. Haga esto así (declaraciones tomadas de pinvoke.net).

[StructLayout(LayoutKind.Sequential)] 
struct MOUSEINPUT 
{ 
    public int dx; 
    public int dy; 
    public uint mouseData; 
    public uint dwFlags; 
    public uint time; 
    public IntPtr dwExtraInfo; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct KEYBDINPUT 
{ 
    public ushort wVk; 
    public ushort wScan; 
    public uint dwFlags; 
    public uint time; 
    public IntPtr dwExtraInfo; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct HARDWAREINPUT 
{ 
    public int uMsg; 
    public short wParamL; 
    public short wParamH; 
} 

[StructLayout(LayoutKind.Explicit)] 
struct MouseKeybdHardwareInputUnion 
{ 
    [FieldOffset(0)] 
    public MOUSEINPUT mi; 

    [FieldOffset(0)] 
    public KEYBDINPUT ki; 

    [FieldOffset(0)] 
    public HARDWAREINPUT hi; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct INPUT 
{ 
    public uint type; 
    public MouseKeybdHardwareInputUnion mkhi; 
} 
+0

Hubo una razón por la que tuve que usar SendInput cuando comencé este proyecto, pero no recuerdo por qué. Sin embargo, esto funciona! ¡Muchas gracias! – Cheetah

5

dwExtraInfo es un puntero.
Por lo tanto, debe tener 4 bytes de ancho en el código de 32 bits y 8 bytes en el código de 64 bits.

para hacer eso en C#, utilice IntPtr (no uint, que es siempre 4 bytes)

+0

He intentado cambiar esto, pero no funcionó con x64 de nuevo (x86 era bien con el cambio). Gracias. – Cheetah

+1

@Ben: Su tamaño es incorrecto. El tamaño varía con el bitness, por lo que no puede especificarlo. – SLaks

+0

Sí, elimine 'LayoutKind.Explicit, Size = 28' y los atributos' FieldOffset'. –

Cuestiones relacionadas