Search code examples
c#winapisendinput

SendInput() does not produce any visible output


I am having problems with getting SendInput function to produce any sort of output. All structs are defined as following ( I have left mouse and hardware ones out) :

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

[StructLayout(LayoutKind.Sequential)]
    public struct KEYBDINPUT
    {
        public ushort wVk;
        public ushort wScan;
        public uint dwFlags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

I send keys in the following way:

SetForegroundWindow(hProc); // using user32.dll switch to desired process
// send keydown 
INPUT iKeyDown = new INPUT();
KEYBDINPUT sKeysDown = new KEYBDINPUT();
iKeyDown.type = KEYBD_INPUT_TYPE;
iKeyDown.ki = sKeysDown;
sKeysDown.wVk = 0;
sKeysDown.wScan = (ushort)0x1E;
sKeysDown.dwFlags = 0x0008 ;
sKeysDown.time = 0;
sKeysDown.dwExtraInfo = GetMessageExtraInfo();

I send Key Up event in exactly the same way, except for dwFlags property:

sKeysUp.dwFlags = 0x0008 | 0x0002;

Finally,

INPUT[] aInputs = new INPUT[] { iKeyDown, iKeyUp };
uint result = SendInput(2, aInputs, Marshal.SizeOf(iKeyDown));  // when dll importing, SetLastError = true 
int error = Marshal.GetLastWin32Error();
Debug.WriteLine(result.ToString() + " " + error.ToString());

The outcome of this is, well, no visible output, result variable is always equal to 2 ( the number of successful inputs ) and GetLastWin32Error() returns 0 ( according to error codes, it is a success). Is there anything that I am missing over here? Cheers!


Solution

  • And I have answered my own question - I was filling in structs incorrectly. Instead of

    INPUT iKeyDown = new INPUT();
    KEYBDINPUT sKeysDown = new KEYBDINPUT();
    iKeyDown.type = KEYBD_INPUT_TYPE;
    iKeyDown.ki = sKeysDown;
    sKeysDown.wVk = 0; // etc
    

    I should have been doing

    INPUT iKeyDown = new INPUT();
    iKeyDown.type = KEYBD_INPUT_TYPE;
    iKeyDown.ki.wvK = 0; // etc
    

    instead. That new KEYBDINPUT() was messing things up. I did also put Mouse/Keyboard/Hardware union in its own separate struct as GSerg suggested. Now it is working as intended.