0

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!

Ryan T. Grimm
  • 1,307
  • 1
  • 9
  • 17
AlexanderM
  • 81
  • 1
  • 2
  • 7
  • Your SetForegroundWindow() call is borken. *Never* ignore the return value of winapi functions. It takes a window handle, not a process handle. – Hans Passant Jul 22 '14 at 21:49
  • @HansPassant It is the case if a badly called variable I guess. I get it using `FindWindow(null, WINDOW_HEADER_NAME) and it is a window handle and not something else. It works as expected, returns True. I should probably rename that variable. – AlexanderM Jul 22 '14 at 21:57
  • @Lambdaλ MouseInput, KeyboardInput, HardwareInput are a union. Look here - http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270%28v=vs.85%29.aspx – AlexanderM Jul 22 '14 at 22:09
  • 1
    @PsyXandeR You're [doing it wrong anyway](http://blogs.msdn.com/b/oldnewthing/archive/2009/08/13/9867383.aspx). – GSerg Jul 22 '14 at 22:11
  • You ignore the return values of calls. Not good. The union should be done Raymond's way. Easier by far to use SendKeys. Or automation. Perhaps the other app doesn't like faked input. You did test with Notepad right? – David Heffernan Jul 23 '14 at 06:23
  • Came here cause my SendInput was not sending mouse events, and discovered my FieldOffset was wrong for the union. Thanks! – FranciscoNabas Jun 04 '23 at 15:37

1 Answers1

0

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.

AlexanderM
  • 81
  • 1
  • 2
  • 7