SendInput 和 64 位

2023-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]));
    }

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

这一切都源于这样一个事实:您只包含了KEYBRDINPUT结构体INPUT. The MOUSEINPUT结构体大于KEYBRDINPUT这就是你的问题的原因。

最好的解决方案是正确定义 INPUT 结构,包括 union 部分。这样做(声明取自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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SendInput 和 64 位 的相关文章

  • 使用实体框架、代码优先方法解决结构问题

    我目前正在使用 EF 和代码优先方法从现有系统构建数据库 最好对 核心 类进行最小的更改 因此 我想找到 Structs 和 EF 的解决方法 是否可以以任何方式将 Struct 包装到类中 以便 EF 可以使用此 Struct 中的数据
  • 如何确定任务栏位于哪个屏幕

    Screen PrimaryScreen 并不总是有效 因为在多显示器设置中 用户可能会将其任务栏移动到主屏幕以外的屏幕 找到具有最小工作区域的屏幕也不起作用 因为可能存在具有不同分辨率的显示器 有什么办法可以通过任务栏定位屏幕吗 您可以使
  • Outlook 2007 捕获 ReplyToAll 事件的共享加载项

    我正在使用 VS 2010 和 Dot Net Framework 2 0 我已在 扩展性 gt Outlook 共享加载项 中创建了一个项目 我正在尝试捕获 ReplyToAll 事件 但它没有被解雇 请看下面的代码 连接方法 inspe
  • Microsoft.NETCore.App 和 Microsoft.NETCore.Platforms 的传递依赖项如何工作

    我很难弄清楚传递依赖项的版本解析如何适用于框架 元包 我问的原因是 似乎每次我们引入 旧 依赖项时 例如指向的东西netstandard2 0或者 2 1 我们最终得到了一长串过时的包 我们的构建管道再次报告了这一点 举个例子 给定一个 n
  • 即使更新语句没有影响任何行,ExecuteNonQuery 返回 1

    我在这里面临一个非常奇怪的问题 我的 DAL 是使用编写的OdbcConnection对象并且工作完美 然而 我必须尊重一些要求 因此必须移动系统来使用MySqlConnection 你会说 不应该有任何问题 但是 现在有一点误解 当我执行
  • WCF 缓存解决方案 - 需要建议

    我工作的公司正在寻求实施缓存解决方案 我们托管了多个 WCF Web 服务 并且需要缓存某些可以持久保存和获取的值 无论客户端与服务的会话如何 我正在研究以下技术 缓存应用程序块 4 1 使用 HttpRuntime 缓存的 WCF TCP
  • 还有其他原因说明我应该考虑忽略发出默认值是一种不好的做法吗?

    我已经使用 WCF 一段时间了 并且在客户端和服务器倾向于共同发布的地方 也就是说 新版本几乎总是同时发布 互操作性和版本控制不是问题 至少在这种情况下 MSDN 文档 DataMemberAttribute EmitDefaultValu
  • 无法在 Web 服务器上启动调试。远程服务器返回错误:(404) 未找到。在 Visual Studio 中启动调试时出错

    我已经将项目设置为在 IIS 上运行一段时间了 当我按 F5 时 它确实连接没有问题 但最近它停止工作 当我按 F5 press 时确实收到此错误Debug gt Start debugging 无法在 Web 服务器上启动调试 远程服务器
  • 为 Rest Web 服务创建 WCF 代理

    我有一个复杂的 WCF Rest 服务 它需要多个输入和对象 我不能简单地通过在 Fiddler 中执行 HTTP POST 来调用它 因为要提供的数据太多 我可以 但这将花费我很长时间 所以我想使用代理在代码中完成它 有没有办法为 NET
  • 哪个更快:清除集合或实例化新集合

    我的代码中有一些通用列表 其中有数十或数百个元素 有时我需要用其他对象重新填充此列表 所以问题是 调用什么会更快Clear 方法或创建一个new List
  • 调用异步方法在视图模型的构造函数中加载数据有警告

    我的视图包含一个 ListView 它显示来自互联网的一些数据 我创建一个异步方法来加载数据并在我的视图模型的构造函数中调用该方法 它有一个警告提示我现在使用await关键字 还有其他解决方案可以在构造函数中异步加载数据吗 有几种可以应用的
  • Gremlin.net 文本包含等效项

    我正在使用 Gremlin net 库连接到 janus 图形服务器 我使用 cassandra 和弹性搜索进行数据存储和索引 在我使用的 gremlin 语言和 gremlin 控制台中文本包含在属性的文本中进行搜索 我正在使用混合索引
  • 如何检测应用程序正在运行的 .NET 版本?

    我尝试使用Environment Version ToString 确定目标计算机上正在使用什么 NET 框架 但安装了 4 0 版本时 它说我正在使用 NET 2 0 如何检测目标计算机上正在运行的 NET Framework 版本 En
  • 使用 System.Text.Json.Serialization.JsonConverter 解析 JSON 序列化过程中复杂类型的循环引用

    有一个复杂类型引用相同类型的对象 有时是同一对象 public class User public string Name get set public int Age get set public User Reference get s
  • 如何在 Windows 窗体中制作窗体模式?

    我正在尝试创建一个子表单 帮助用户在父表单中的字段中输入数据 我希望这个子表单是模态的 但是我需要做什么才能使这个表单成为模态 我需要使用其他类型的物品吗 Use Form ShowDialog http msdn microsoft co
  • String.Format - 它如何工作以及如何实现自定义格式字符串

    With String Format 例如可以格式化DateTime对象以许多不同的方式 每次我寻找所需的格式时 我都需要在互联网上搜索 我几乎总能找到一个可以使用的例子 例如 String Format 0 MM dd yyyy Date
  • Python中非常大的整数的math.pow是错误的[重复]

    这个问题在这里已经有答案了 我试图通过计算一个整数的非常大的幂来打印一个非常大的数字 尽管我的代码是正确的 但我没有观察到所需的输出 一般来说 Python解释器可以打印系统内存支持的非常大的整数 考虑到这个假设 下面是我正在运行的代码 a
  • 运行 C# exe 文件

    复制 为什么我的 NET 应用程序在从网络驱动器运行时会崩溃 https stackoverflow com questions 148879 why does my net application crash when run from
  • 析构函数、dispose 和 Finalize 方法之间的区别

    我正在研究垃圾收集器在 C 中的工作原理 我对使用感到困惑Destructor Dispose and Finalize方法 根据我的研究和理解 在我的类中拥有析构函数方法将告诉垃圾收集器以析构函数方法中提到的方式执行垃圾收集 该方法不能在
  • 我们可以使用 C# 录制发送到扬声器的声音吗

    我有一个软件 SoundTap Streaming Audio Recorder 它记录发送到扬声器的任何音频 无论流是来自网络还是来自某些文件或麦克风 我可以在桌面应用程序中制作这样的应用程序 以便我可以录制发送到扬声器的流 无论来源如何

随机推荐