0

The goal is to programatically hit Enter to some cmd.exe (running in background, e.g. owned by SYSTEM user, started from a windows service) which would visually result in a new, empty promt line like "C:\dev\sendenter>".

All i found on the net concentrates on receiving the keys where you have the option to check if ascii code 10 or 13 was sent. But when sending those to a running cmd.exe, all that will happen is that you get a newline but no new command prompt. Even using VK_RETURN which should be an alias for Carriage Return and Line Feed does not end up in a new prompt.

I believe the problem could be that WM_KEYUP or such must follow the ASCII key 10 or 13 but i was not able to find out how to send this using below minimal example.

#include <Windows.h>
#include <stdio.h>

//argument: int PID of process
//compile with gcc, no options

//first and only argument: int PID
int main(int argc, char** argv){
    DWORD pid = atoi(argv[1]);
    printf ("Argument PID: %d\n",pid);

    if (!FreeConsole())
    {
        printf("Could not FreeConsole\n");
        exit(1);
    }
    if (!AttachConsole(pid)){
        printf("Error: could not attach console to specified PID\n");
        exit(2);
    }

    char s[] = {VK_RETURN};
    HANDLE stdoutt = GetStdHandle(STD_OUTPUT_HANDLE);
    unsigned long cChars;
    WriteConsole(stdoutt, s, lstrlen(s), &cChars, NULL);

    return 0;
    
}
Harry
  • 1,233
  • 10
  • 24
  • Does `lstrlen()` require a NUL terminated string? In this case you need `char s[] = {VK_RETURN, '\0'};` – David Ranieri Sep 27 '21 at 18:43
  • good point, i was not sure if the null terminator is added automatically when defining the char array but i tested it with char s[] = {VK_RETURN, '\0'}; and it dont make a difference unfortunately. The receiving commandline just draws a newline but does not end up with a fresh prompt – Harry Sep 27 '21 at 20:01
  • I think you can try with `WriteConsoleInput` [here](https://stackoverflow.com/q/5880173/453348) a sample – tttony Sep 27 '21 at 20:04
  • i did read the post but not try it, now i did but the result stays the same for me, not 100% sure if i did what you had in mind @tttony https://pastebin.com/LCTYGcH1 in the end i dont think it matters if i write to stdin or stdout as soon as i attached to the other console, at least this is what i seem to experience – Harry Sep 27 '21 at 20:24

1 Answers1

1

Tested on VS 2013

int main(int argc, char** argv){
    DWORD pid = atoi(argv[1]);

    if (!FreeConsole())
    {
        printf("Could not FreeConsole\n");
        exit(1);
    }
    if (!AttachConsole(pid)){
        printf("Error: could not attach console to specified PID\n");
        exit(2);
    }

    HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD ir[2];
    DWORD dwTmp = 0;
    
    ir[0].EventType = KEY_EVENT;
    ir[0].Event.KeyEvent.bKeyDown = TRUE;
    ir[0].Event.KeyEvent.dwControlKeyState = 0;
    ir[0].Event.KeyEvent.uChar.UnicodeChar = '\r';
    ir[0].Event.KeyEvent.wRepeatCount = 1;
    ir[0].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
    ir[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
    
    ir[1].EventType = KEY_EVENT;
    ir[1].Event.KeyEvent.bKeyDown = FALSE;
    ir[1].Event.KeyEvent.dwControlKeyState = 0;
    ir[1].Event.KeyEvent.uChar.UnicodeChar = '\r';
    ir[1].Event.KeyEvent.wRepeatCount = 1;
    ir[1].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
    ir[1].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
    
    WriteConsoleInput(hConsole, ir, 2, &dwTmp); // <-- 2 it's the number of inputs to send

    return 0;
}

I just tested with only cmd.exe opened and sending input to that process, at the beginning it only typed ? in the console, that's because you have to send two inputs, the first with the bKeyDown to TRUE and later FALSE and UnicodeChar is setted to \r instead of \n

Also I had to set wRepeatCount to 1 because it was triggering asserts

Microsoft says:

wRepeatCount

The repeat count, which indicates that a key is being held down. For example, when a key is held down, you might get five events with this member equal to 1, one event with this member equal to 5, or multiple events with this member greater than or equal to 1.

Remember that any printf will be sent to the attached console and can mess up the input

tttony
  • 4,944
  • 4
  • 26
  • 41