2011-07-26 28 views
10

Dưới đây là một đoạn trích của một số mã tôi đang sử dụng để mô phỏng các lần nhấn phím thông qua API SendInput. Điều này hoạt động chính xác nếu tôi thiết lập ứng dụng của tôi để biên dịch cho một CPU x86, nhưng không làm việc cho việc biên dịch CPU x64.SendInput và 64bits

Tôi đoán nó có điều gì đó cần làm với thực tế là x64 sử dụng con trỏ kích thước gấp đôi, nhưng tôi đã cố gắng thay đổi này [FieldOffset(4)] thành [FieldOffset(8)] nhưng nó không hoạt động.

Có thể liên quan đến thực tế việc nhập phiên bản 32 bit của user32.dll không?

#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

Bằng cách nào đó, một số mã đã mất tích do đó, dòng trong câu hỏi nên đọc '[StructLayout (LayoutKind.Explicit, Kích thước = 28)]' – Cheetah

Trả lời

11

Tiếp tục đến lỗi mà SLaks xác định, vấn đề còn lại của bạn là kích thước của INPUT là không chính xác. Điều này có nghĩa là SendInput không thành công vì nó nhận được thông số loại INPUT[]. Bạn không thể chỉ định kích thước với StructLayout(LayoutKind.Explicit, Size = 28) vì bạn muốn mã xử lý cả x86 và x64.

Tất cả điều này bắt nguồn từ thực tế là bạn chỉ bao gồm cấu trúc KEYBRDINPUT trong INPUT. Cấu trúc MOUSEINPUT lớn hơn KEYBRDINPUT là nguyên nhân gây ra sự cố của bạn.

Giải pháp tốt nhất là xác định cấu trúc INPUT chính xác, bao gồm phần công đoàn. Làm như vậy (các tờ khai được lấy từ 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

Có một lý do tôi phải sử dụng SendInput khi tôi bắt đầu dự án này nhưng tôi không thể nhớ tại sao. Tuy nhiên - công trình này! Cảm ơn nhiều! – Cheetah

5

dwExtraInfo là con trỏ.
Vì vậy, nó cần phải rộng 4 byte trong mã 32 bit và 8 byte trong mã 64 bit.

Để làm điều đó trong C#, sử dụng IntPtr (không uint, mà luôn luôn là 4 byte)

+0

tôi đã cố gắng thay đổi điều này, nhưng nó đã không làm việc với x64 lần nữa (x86 là tốt với sự thay đổi). Cảm ơn. – Cheetah

+1

@Ben: Kích thước của bạn sai. Kích thước thay đổi theo bit, do đó bạn không thể chỉ định kích thước. – SLaks

+0

Có, loại bỏ các thuộc tính 'LayoutKind.Explicit, Size = 28' và' FieldOffset'. –

Các vấn đề liên quan