I am trying to simulate mouse and keyboard events by using SendInput()
in C#. The mouse simulated perfectly, while the simulation for the keyboard is not working.
In that case, I tried to use another language to hook the keyboard to determine if it really works, but I could not hook anything. I tried to see if there are any errors, but Marshal.GetLastWin32Error()
returns 0
, which means there is no error. I also tried to run as administrator, but it did not work.
After that, I found a similar situation on StackOverflow, and I tried to change the code to KeyEventFlags.KEYDOWN | KeyEventFlags.SCANCODE
and KeyEventFlags.KEYDOWN | KeyEventFlags.UNICODE
, but they both did not work.
Here is the code:
[DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
KEYBDINPUT keyboardInput = new KEYBDINPUT();
keyboardInput.dwFlags = (uint)(KeyEventFlags.KEYDOWN);
keyboardInput.wVk = (ushort)'A';
InputUnion union = new InputUnion();
union.ki = keyboardInput;
INPUT[] input = new INPUT[1];
input[0].type = (uint)InputTypes.KEYBOARD;
input[0].U = union;
Console.WriteLine(SendInput(1, input, Marshal.SizeOf(union)));
Console.WriteLine(Marshal.GetLastWin32Error());
Note: I only press the key down, but it should still return 1
and have been hooked, while it returns 0
now.
Here is the code that defines enums:
public enum InputTypes : uint
{
MOUSE = 0,
KEYBOARD = 1,
HARDWARE = 2
}
public enum MouseEventFlags : uint
{
ABSOLUTE = 0x8000,
LEFTDOWN = 0x0002,
LEFTUP = 0x0004,
MIDDLEDOWN = 0x0020,
MIDDLEUP = 0x0040,
MOVE = 0x0001,
RIGHTDOWN = 0x0008,
RIGHTUP = 0x0010,
WHEEL = 0x0800,
XDOWN = 0x0080,
XUP = 0x0100,
HWHEEL = 0x01000
}
public enum KeyEventFlags : ushort
{
KEYDOWN = 0x0000,
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
UNICODE = 0x0004,
SCANCODE = 0x0008
}
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
public uint type;
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 ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}
I wonder why this is not working, and which step I got wrong.
As far as I'm concerned, you need to use KEYEVENTF_KEYUP
to release the key.
And I agree with Simon, cbSize
is the size, in bytes, of an INPUT structure. You should need to use Marshal.SizeOf(typeof(INPUT))
instead of Marshal.SizeOf(union)
.
You could refer to the links:
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput#example