Thread: SendInput

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    930

    SendInput

    I cant find out why when i call Enter(0x1c) in inp[2] and inp[3] the KEYEVENTF_KEYUP flag not working so the key stays pressed forever.

    I recreated a simplified code without the string part and there it was working well.
    So maybe its coming from there.

    Code:
    SendString(_T("dellserv"), 0x1c);
    
    static void SendString(LPCTSTR str, int ScanCode)
    {
        INPUT inp[4];
        memset(inp,0,sizeof(INPUT));
        inp[0].type = INPUT_KEYBOARD;
        inp[0].ki.dwFlags  = KEYEVENTF_UNICODE;
        inp[1] = inp[0];
        inp[1].ki.dwFlags |= KEYEVENTF_KEYUP;
        inp[2] = inp[0];
        inp[2].ki.dwFlags  = KEYEVENTF_SCANCODE;
        inp[3] = inp[0];
        inp[3].ki.dwFlags |= KEYEVENTF_KEYUP;
    
        for (LPCTSTR p=str; *p; p++)
        {
            inp[0].ki.wScan = inp[1].ki.wScan = *p;
            SendInput(4, &inp[0], sizeof(INPUT));
            SendInput(4, &inp[1], sizeof(INPUT));
        }
    
        if(ScanCode != 0)
        {
            inp[2].ki.wScan = inp[3].ki.wScan = ScanCode;
            SendInput(4, &inp[2], sizeof(INPUT));
            SendInput(4, &inp[3], sizeof(INPUT));
        }
    }
    Using Windows 10 with Code Blocks and MingW.

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    What does GetLastError() return?

    Why do you only set the type in the first INPUT union?

    What happens when you watch this loop in the debugger?

    Code:
    for (LPCTSTR p=str; *p; p++)
        {
            inp[0].ki.wScan = inp[1].ki.wScan = *p;
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    1.Every SendInput returning 4 as they are meant to, so there is no error.

    2.The type of input is reset everytime i reassign the whole previous structure:
    Code:
    inp[2] = inp[0];
    or is there something wrong with that?

    3.I dont know how to debug yet, i guess its time to learn it now.

    Anyway the program is working its just that the last button stays stuck at the end.
    I saw it with GetAsyncKeyState.
    Using Windows 10 with Code Blocks and MingW.

  4. #4
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Ok i debugged it with Windbg but i dont know how to interpret it.
    I set a breakpoint on SendInput but it didnt break on it.

    Could somebody help me?

    Code:
    0:000> bu USER32.dll!SendInput
    0:000> g
    ModLoad: 76bb0000 76c10000   C:\Windows\SysWOW64\IMM32.DLL
    ModLoad: 75e50000 75f1c000   C:\Windows\syswow64\MSCTF.dll
    ModLoad: 73690000 736ab000   C:\Windows\SysWOW64\nvinit.dll
    ModLoad: 73280000 732cc000   C:\Windows\SysWOW64\apphelp.dll
    ModLoad: 49f40000 49f8c000   cmd.exe 
    eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=77672100 edi=776720c0
    eip=7758fcb2 esp=0045fc84 ebp=0045fca0 iopl=0         nv up ei pl zr na pe nc
    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
    ntdll!NtTerminateProcess+0x12:
    7758fcb2 83c404          add     esp,4
    Using Windows 10 with Code Blocks and MingW.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Perhaps set a breakpoint on SendInputW, if you compiled for UNICODE.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    I looked up on MSDN before and there was no two versions of it thats why i ran it just as SendInput.

    But even if i run it as SendInputA or SendInputW it doesnt make a difference, it wont break.

    By the way i compiled the .exe with the -Zi switch.

    I dont know if that counts.
    Using Windows 10 with Code Blocks and MingW.

  7. #7
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by Salem View Post
    Perhaps set a breakpoint on SendInputW, if you compiled for UNICODE.
    There is no SendInputW since the function doesn't have a c-string parameter

    OP: the first number to SendInput is the number of inputs. Setting it to 4 for anything except the first call access memory that contains who knows what, it also means that it tries to send all four inputs when you should be only sending the first two. Using it twice in first loop means it tries to send 8 inputs per character. Look at the code you copied from, it sends a both a down and a up keystroke but only uses SendInput once.

    No offence but regardless of how many hours a day/week you devote to programming, after three and a half years, magic numbers, guessing and not reading the documentation should be mistakes that are far behind you.

  8. #8
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thank you Adeyblue for taking the time and helping me.

    No offence taken, i know im not the brightest crayon in the box.

    Still, having said that, i was aware that the first arg is the number of structures but in the second arg i only call 1,2 and 3,4 respectively.

    So see i thought it was possible to do it that way.

    Fortunately you tell me its not so ill be able to fix this code.

    By the way neither Salem nor Novocain caught on it but maybe they werent looking at it too hard.
    Last edited by Ducky; 07-23-2011 at 09:48 AM.
    Using Windows 10 with Code Blocks and MingW.

  9. #9
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Here's an example sending the letter 'a'

    Code:
    INPUT inp[2] = {0};
    
    inp[0].type = INPUT_KEYBOARD;
    inp[0].ki.wVk = VK_A;  // this can be a lower case ascii value from a c string.
    inp[1].type = INPUT_KEYBOARD;
    inp[1].ki.wVk = VK_A;
    inp[1].ki.dwFlags = KETEVENTF_KEYUP;
    
    SendInput(2,&inp,sizeof(INPUT));
    Also note that in order to manipulate shift, alt or ctrl keys along with the sent character you may need to send more than 2 inp structs... for example to send a capital a you will need to first do shift key down, then a key down, a key up and finally shift key up... a total of 4 structs. For multikey combinations you may have to send as many as 8.

    Since this will only send to the focused window or control, a far more reliable method --provided you know the window or thread handle-- is to use either PostMessage() or PostThreadMessage() directly to the desired program sending WM_KEYDOWN and WM_KEYUP messages.
    Last edited by CommonTater; 07-23-2011 at 10:44 AM.

  10. #10
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thanks CommonTater for your effort but look again at the function i posted.

    It can send perfectly well even a string.

    What i was trying to add to this function is the possibility to press a button after a sending a string.

    I tried to follow Adeyblue advice and reduced the input structure size to two but the issue stays the same (the key stays down).

    I think the problem is the use of KEYEVENTF_UNICODE and KEYEVENTF_SCANCODE together, even if it gets overwritten.
    Last edited by Ducky; 07-23-2011 at 02:08 PM.
    Using Windows 10 with Code Blocks and MingW.

  11. #11
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Ducky View Post
    Thanks CommonTater for your effort but look again at the function i posted.

    It can send perfectly well even a string.

    What i was trying to add to this function is the possibility to press a button after a sending a string.

    I tried to follow Adeyblue advice and reduced the input structure size to two but the issue stays the same (the key stays down).

    I think the problem is the use of KEYEVENTF_UNICODE and KEYEVENTF_SCANCODE, even if it gets overwritten.
    More likely the problem is that you are sending everything twice...
    The second time starts at inp[1] and is sending 4 packets which means you are sending garbage beyond the end of your array.
    Send it once... and only once starting at inp[0].

    Also take a look at the API description of the function, you probably don't want to use either unicode or scancode flags in there, since you are sending a string you want to send virtual keys along with shift keys for capital letters....

    SendInput Function (Windows)

  12. #12
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    No its not sending four packets.
    If it was the case when you send this it should send 2 packets too
    and it shouldnt work either.
    (I put two structure in the first arg as in the original code)

    Code:
    SendInput(2, &inp[0], sizeof(INPUT));
    You cant send it once because you have to change the flag for the second time for the the key to be released.
    Using Windows 10 with Code Blocks and MingW.

  13. #13
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    From your original code sample...
    Code:
        for (LPCTSTR p=str; *p; p++)
        {
            inp[0].ki.wScan = inp[1].ki.wScan = *p;
            SendInput(4, &inp[0], sizeof(INPUT));
            SendInput(4, &inp[1], sizeof(INPUT));    
        }
    
        if(ScanCode != 0)
        {
            inp[2].ki.wScan = inp[3].ki.wScan = ScanCode;
            SendInput(4, &inp[2], sizeof(INPUT));       
            SendInput(4, &inp[3], sizeof(INPUT));    
         }
    From MSDN's description of this function...

    UINT WINAPI SendInput(
    __in UINT nInputs,
    __in LPINPUT pInputs,
    __in int cbSize
    );
    nInputs is the number of structs in the array...
    pInputs is a pointer to the first struct...

    When you use SendInput(4 ... you are telling it to send 4 structs, that is, 4 events to the input queue.

    With what you have it is going to send 4 structs starting at different offsets in your array... the last one is going to send &inp[3], inp[4], inp[5], inp[6] ... from an array declared as inp[4].

    So yes you are sending junk from out of bounds of your array.

    SendInput Function (Windows)
    Last edited by CommonTater; 07-24-2011 at 07:21 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. SendInput()
    By borre_mosch in forum Windows Programming
    Replies: 1
    Last Post: 01-13-2004, 11:36 AM
  2. SendInput()?
    By src in forum Windows Programming
    Replies: 11
    Last Post: 02-21-2003, 07:43 PM
  3. tagINPUT sendINput
    By Unregistered in forum Windows Programming
    Replies: 3
    Last Post: 03-09-2002, 06:14 PM
  4. tagINPUT and SendInput
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 03-08-2002, 03:08 PM