2011-07-26 10 views
10

Poniżej znajduje się fragment kodu, którego używam do symulacji naciśnięć klawiszy za pośrednictwem interfejsu SendInput API. Działa to poprawnie, jeśli ustawię moją aplikację na kompilację dla procesora x86, ale nie działa to przy kompilacji CPU x64.SendInput and 64bits

Zgaduję, że ma coś todo z tym, że x64 używa wskaźników podwójnego rozmiaru, ale próbowałem zmienić ten [FieldOffset(4)] na ten [FieldOffset(8)], ale to nie zadziałało.

Czy może to mieć coś wspólnego z faktem, że importuje on 32-bitową wersję 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

Jakoś niektóre kod brakowało więc linia powinna czytać '[StructLayout (LayoutKind.Explicit, Size = 28)]' – Cheetah

Odpowiedz

11

Dalsze do błędu, że SLaks zidentyfikowane, Twój pozostały problemem jest to, że wielkość INPUT jest nieprawidłowy. Oznacza to, że SendInput kończy się niepowodzeniem, ponieważ otrzymuje parametr typu INPUT[]. Nie możesz określić rozmiaru przy pomocy StructLayout(LayoutKind.Explicit, Size = 28), ponieważ potrzebujesz kodu obsługującego zarówno x86, jak i x64.

Wszystko to wynika z faktu, że uwzględniono tylko strukturę KEYBRDINPUT w INPUT. Struktura MOUSEINPUT jest większa niż KEYBRDINPUT, co jest przyczyną problemu.

Najlepszym rozwiązaniem jest prawidłowe zdefiniowanie struktury INPUT, w tym części związanej. Zrób to tak (deklaracje zaczerpnięte z 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

Był powód, dla którego musiałem użyć SendInput kiedy zacząłem ten projekt, ale nie pamiętam dlaczego. Jednak - to działa! Dziękuję Ci bardzo! – Cheetah

5

dwExtraInfo to wskaźnik.
Dlatego musi mieć szerokość 4 bajtów w kodzie 32-bitowym i 8 bajtów w kodzie 64-bitowym.

to zrobić w C#, użyj IntPtr (nie uint, który jest zawsze 4 bajty)

+0

Próbowałem zmienia to jednak nie działa z znowu x64 (x86 był dobrze ze zmianą). Dzięki. – Cheetah

+1

@Ben: Twój rozmiar jest nieprawidłowy. Rozmiar różni się w zależności od bitness, więc nie można go określić. – SLaks

+0

Tak, usuń atrybuty 'LayoutKind.Explicit, Size = 28' i' FieldOffset'. –