You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中SendInput无法正常模拟键盘事件的问题排查

问题分析与修复方案

核心错误:SendInput的cbSize参数错误

你的代码调用SendInput时传入的cbSize是Marshal.SizeOf(union),但根据Win32 API规范,该参数必须是单个INPUT结构体的大小,而非InputUnion的大小。这是导致SendInput返回0(调用失败)的直接原因。

其他潜在问题

  • 仅模拟按键按下,未释放:多数程序需要完整的"按下+释放"事件才会响应单个按键操作,仅模拟按下可能无法触发预期行为。
  • wVk赋值不规范:直接用(ushort)'A'虽能得到A键的虚拟键码0x41,但更稳妥的方式是直接使用虚拟键码值(如0x41),避免字符编码差异引发问题。
  • 未初始化冗余字段:KEYBDINPUT的wScan、time、dwExtraInfo字段未显式初始化,内存中的垃圾值可能干扰API执行。

修复后的代码示例

修正SendInput调用逻辑

// 传入INPUT结构体的大小作为cbSize参数
uint result = SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));
Console.WriteLine(result);
Console.WriteLine(Marshal.GetLastWin32Error());

完整的A键模拟(按下+释放)

// 构造按下事件
KEYBDINPUT keyDown = new KEYBDINPUT();
keyDown.wVk = 0x41; // A键的虚拟键码
keyDown.dwFlags = (uint)KeyEventFlags.KEYDOWN;
keyDown.wScan = 0;
keyDown.time = 0;
keyDown.dwExtraInfo = IntPtr.Zero;

// 构造释放事件
KEYBDINPUT keyUp = new KEYBDINPUT();
keyUp.wVk = 0x41;
keyUp.dwFlags = (uint)(KeyEventFlags.KEYUP);
keyUp.wScan = 0;
keyUp.time = 0;
keyUp.dwExtraInfo = IntPtr.Zero;

InputUnion unionDown = new InputUnion();
unionDown.ki = keyDown;

InputUnion unionUp = new InputUnion();
unionUp.ki = keyUp;

INPUT[] inputs = new INPUT[2];
inputs[0].type = (uint)InputTypes.KEYBOARD;
inputs[0].U = unionDown;
inputs[1].type = (uint)InputTypes.KEYBOARD;
inputs[1].U = unionUp;

// 执行模拟
uint result = SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT)));
Console.WriteLine($"成功发送的输入数:{result}");
Console.WriteLine($"错误码:{Marshal.GetLastWin32Error()}");

额外说明

  • 若需模拟Unicode字符,需设置dwFlags = KeyEventFlags.KEYDOWN | KeyEventFlags.UNICODE,同时将wVk设为0,wScan赋值为目标Unicode字符的代码值。
  • 模拟前确保目标窗口处于激活状态,否则键盘事件可能无法被捕获。

内容的提问来源于stack exchange,提问作者Han Han

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:02:52