SendInput和64位

Che*_*tah 10 .net 64-bit pinvoke sendinput

下面是我用来通过SendInput API模拟按键的一些代码的摘录.如果我将我的应用程序设置为针对x86 CPU进行编译,则此方法可正常工作,但不适用于x64 CPU编译.

我猜它有一些事情,x64使用双倍大小的指针,但我试图改变这个[FieldOffset(4)],[FieldOffset(8)]但它没有用.

它是否与导入32位版本的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]));
    }
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 12

除了SLaks发现的错误之外,您剩下的问题是大小INPUT不正确.这意味着SendInput失败,因为它接收到类型的参数INPUT[].您无法指定大小,StructLayout(LayoutKind.Explicit, Size = 28)因为您需要处理x86和x64的代码.

这一切都源于你只包含了KEYBRDINPUT结构的事实INPUT.该MOUSEINPUT结构是大于KEYBRDINPUT这是你的问题的原因.

最佳解决方案是正确定义INPUT结构,包括联合部分.这样做(从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;
}
Run Code Online (Sandbox Code Playgroud)


SLa*_*aks 5

dwExtraInfo是一个指针.
因此,它需要在32位代码中为4字节宽,在64位代码中为8字节.

要在C#中执行此操作,请使用IntPtr(不是uint,总是4个字节)