dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7

Thread: How to inject input text into a running console application

  1. #1
    Join Date
    Nov 2003
    Location
    Portland, OR
    Posts
    894

    How to inject input text into a running console application

    My goal is to be able to inject text into a separate console application. I am able to access a running console process (using DLL injection method) where I can execute the following code from within that console process:

    Code:
    //'pStrTxt' = Unicode text to insert into console
    
    HANDLE hStdOut;
    hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
    
    int nchLn = lstrlen(pStrTxt);
    
    DWORD dwchLnWrtn = -1;
    if(::WriteConsole(hStdOut, pStrTxt, nchLn, &dwchLnWrtn, NULL) &&
        dwchLnWrtn == nchLn)
    {
        //Done
    }
    This works fine and I can see my injected text in the console window, but there's one problem. If the console app was expecting user input, and if I hit enter after my injection of text, none of my text will be registered.

    To illustrate it, assume the target console app was running the following code:
    Code:
    std::string str;
    for(;;)
    {
        std::getline(cin, str);
        printf("%s\n", str.c_str());
    }
    If I run it and just type some text and hit enter, it will double my typed up text on the next line by outputting what was typed in the str variable.

    But if I inject my code into this console app (using the first code sample above) the text will appear in the console window, but when I hit enter my str variable will be empty as if nothing was there.

    So what am I missing in my text injection code (in the first sample)?

  2. #2
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,714

    Re: How to inject input text into a running console application

    I think you need to use the WriteConsoleInput() function. See https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.1.3)

  3. #3
    Join Date
    Nov 2003
    Location
    Portland, OR
    Posts
    894

    Re: How to inject input text into a running console application

    Oh man, thanks a lot. Although WriteConsoleInput() is not easy to use, but that did it.

  4. #4
    Join Date
    Nov 2003
    Location
    Portland, OR
    Posts
    894

    Re: How to inject input text into a running console application

    Here's the code that I came up with. As you see using that API "slightly" complicates things

    There's one issue though. It doesn't seem to work with Unicode characters. Just as an example, if I copy "big δέντρο tree" string and then paste it into Windows Power Shell it gets inserted correctly:

    Name:  good.png
Views: 153
Size:  2.8 KB

    but if I run the same string through the code below I get this:

    Name:  bad.png
Views: 151
Size:  2.6 KB

    (Note that the string is not butchered by an encoding inside my process.)

    Any idea what am I doing wrong here?


    Code:
    //Error checks are omitted for brevity
    //'pStrTxt' = Unicode text to insert into console
    //LPCTSTR pStrTxt = L"big δέντρο tree";
    
    HANDLE hStdIn = ::GetStdHandle(STD_INPUT_HANDLE);
    
    HKL kbdLt = ::GetKeyboardLayout(NULL);
    
    int nchLn = lstrlen(pStrTxt);
    for(int i = 0; i < nchLn; i++)
    {
    	TCHAR z = pStrTxt[i];
    
    	INPUT_RECORD ir[2] = {0};
    
    	WORD wVkCodeRes = ::VkKeyScanEx(z, kbdLt);
    
    	ir[0].Event.KeyEvent.uChar.UnicodeChar = z;
    	ir[0].Event.KeyEvent.wVirtualKeyCode = wVkCodeRes & 0xFF;
    
    	BYTE byKState = (BYTE)((wVkCodeRes & 0xFF00) >> 8);
    
    	DWORD dwCtrlKState = 0;
    
    	//1 = Either SHIFT key is pressed.
    	//2 = Either CTRL key is pressed.
    	//4 = Either ALT key is pressed.
    	//8 = The Hankaku key is pressed
    	if(byKState & 0x1)
    		dwCtrlKState |= SHIFT_PRESSED;
    
    	if((byKState & 0x6) == 0x6)
    	{
    		//SOURCE:
    		//		https://msdn.microsoft.com/en-us/library/windows/desktop/ms646329(v=vs.85).aspx
    		//
    		//For keyboard layouts that use the right-hand ALT key as a shift key (for example, 
    		//the French keyboard layout), the shift state is represented by the value 6, because 
    		//the right-hand ALT key is converted internally into CTRL+ALT.
    		dwCtrlKState |= RIGHT_ALT_PRESSED;
    	}
    	else
    	{
    		if(byKState & 0x2)
    			dwCtrlKState |= LEFT_CTRL_PRESSED;
    		if(byKState & 0x4)
    			dwCtrlKState |= LEFT_ALT_PRESSED;
    	}
    
    	ir[0].Event.KeyEvent.dwControlKeyState = byKState;
    
    	ir[0].EventType = KEY_EVENT;
    	ir[0].Event.KeyEvent.bKeyDown = TRUE;
    	ir[0].Event.KeyEvent.wRepeatCount = 1;
    
    	//Get virtual scan code
    	UINT uiScanCode = ::MapVirtualKeyEx(ir[0].Event.KeyEvent.wVirtualKeyCode & 0xFF, MAPVK_VK_TO_VSC, kbdLt);
    	ir[0].Event.KeyEvent.wVirtualScanCode = (WORD)uiScanCode;
    
    	ir[1] = ir[0];
    	ir[1].Event.KeyEvent.bKeyDown = FALSE;
    
    	DWORD dwNumWrtn = -1;
    	if(::WriteConsoleInput(hStdIn, ir, 2, &dwNumWrtn) &&
    		dwNumWrtn == 2)
    	{
    		//All good
    	}
    }

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,714

    Re: How to inject input text into a running console application

    What input locale is set for the keyboard? This will effect the virtual keycode used.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.1.3)

  6. #6
    Join Date
    Nov 2003
    Location
    Portland, OR
    Posts
    894

    Re: How to inject input text into a running console application

    US-English in both cases.

  7. #7
    Join Date
    Jan 2019
    Posts
    1

    Re: How to inject input text into a running console application

    Dead thread I know but if anyone is interested the reason this didn't work is because
    ir[0].Event.KeyEvent.dwControlKeyState = byKState;
    should have been
    ir[0].Event.KeyEvent.dwControlKeyState = dwCtrlKState;

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)