【问题标题】:SendInput and 64bitsSendInput 和 64 位
【发布时间】:2011-10-13 10:12:08
【问题描述】:

下面是我用来通过 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]));
    }

【问题讨论】:

  • 不知何故,缺少一些代码,所以有问题的行应该是[StructLayout(LayoutKind.Explicit, Size = 28)]

标签: .net pinvoke 64-bit sendinput


【解决方案1】:

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

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

【讨论】:

  • 我尝试更改此设置,但它再次无法与 x64 一起使用(x86 可以更改)。谢谢。
  • @Ben:你的尺码不对。大小随位数变化,所以不能指定。
  • 是的,删除 LayoutKind.Explicit, Size = 28FieldOffset 属性。
  • @David Heffernan 如果我删除这些,x86 或 x64 都不起作用。我相信他们是需要的。我尝试将 28 -> 32 和 FieldOffset 更改为 8 只是为了看看我是否可以让 x64 工作,但它没有
  • 你大概需要使用LayoutKind.Sequential。是默认的 LayoutKind.Automatic 吗?我不确定。
【解决方案2】:

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

这一切都源于您只在INPUT 中包含KEYBRDINPUT 结构。 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;
}

【讨论】:

  • 开始这个项目时我必须使用 SendInput 是有原因的,但我不记得为什么了。但是 - 这行得通!非常感谢!
【解决方案3】:

对于 64 位平台,唯一需要更改的是 INPUT 的第二个参数的 FieldOffset(8)(而不是 4)。无需更改或指定其余结构的大小。 这就足够了(请注意,我使用默认的InputUnion 结构而不是KEYBDINPUT 而没有区别):

 [StructLayout(LayoutKind.Explicit)]
    public struct INPUT
    {
    [FieldOffset(0)] public uint Type;
    [FieldOffset(8)] public InputUnion U;
    }

    [StructLayout(LayoutKind.Explicit )]
    public struct InputUnion
    {
        [FieldOffset(0)] public MOUSEINPUT mi;
        [FieldOffset(0)] public KEYBDINPUT ki;
        [FieldOffset(0)] public HARDWAREINPUT hi;
    }


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


    [StructLayout(LayoutKind.Sequential)]
    public struct KEYBDINPUT
{
    public UInt16 Vk;
    public UInt16 Scan;
    public UInt32 Flags;
    public UInt32 Time;
    public IntPtr ExtraInfo;
}

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

【讨论】:

    猜你喜欢
    • 2012-02-16
    • 2019-07-09
    • 2013-03-24
    • 2013-03-01
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多