Работа с kbhit в дочернем процессе с перенаправленным stdin - PullRequest
0 голосов
/ 04 сентября 2018

Я написал программу, которая запускает другой процесс и перенаправляет его стандартный ввод / вывод на каналы с помощью API Windows (CreateProcess, CreatePipe и т. Д.)

Программа должна запускать несколько различных консольных программ и взаимодействовать с ними с помощью stdio.

Это все работало хорошо (я мог писать в stdin процесса и читать из процесса, используя каналы), пока не попытался запустить программу и связаться с программой, которая использовала kbhit.

Чтобы упростить то, что та программа, которую я хотел бы запустить, делает со стандартным вводом:

while(1)
{
    if(kbhit())
    {
        fgets(line, sizeof(line), stdin);
        //do something with line
    }
    Sleep(100);
 } 

В результате fgets никогда не вызывается, потому что kbhit не возвращает true, даже если я написал в канал, на который перенаправил stdin. Я знаю это, потому что я отлаживал в другой программе. Я попытался удалить вызов kbhit, и тогда он работает, но я не могу изменить этот код.

Есть ли способ отправить что-то процессу, чтобы этот kbhit в дочернем процессе вернул true?

1 Ответ

0 голосов
/ 04 сентября 2018

Функция _kbhit проверяет консоль на недавнее нажатие клавиши. он никогда не проверяет стандартный ввод, но открывает CONIN$ (консольный ввод) и всегда читает отсюда.

так что перенаправление stdin тут ничего не даст. если мы совместно используем дочернюю консоль, мы можем использовать WriteConsoleInput для этой задачи. пример записи строки в дочерний элемент:

void write_to_conin(PCWSTR msg)
{
    if (ULONG len = (ULONG)wcslen(msg))
    {
        if (INPUT_RECORD* lpBuffer = new INPUT_RECORD[len])
        {
            INPUT_RECORD* pir = lpBuffer;
            ULONG n = len;
            do 
            {
                WCHAR UnicodeChar = *msg++;
                WORD wVirtualKeyCode = UnicodeChar;
                DWORD dwControlKeyState = CAPSLOCK_ON;

                if ((USHORT)(UnicodeChar - 'a') <= (USHORT)('z' - 'a'))
                {
                    dwControlKeyState = 0;
                    wVirtualKeyCode &= ~0x20;
                }

                pir->Event.KeyEvent.bKeyDown = TRUE;
                pir->Event.KeyEvent.dwControlKeyState = dwControlKeyState;
                pir->Event.KeyEvent.wRepeatCount = 1;
                pir->Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
                pir->Event.KeyEvent.wVirtualKeyCode = wVirtualKeyCode;
                pir->Event.KeyEvent.wVirtualScanCode = (WORD)MapVirtualKey(wVirtualKeyCode, MAPVK_VK_TO_VSC);
                pir++->EventType = KEY_EVENT;
            } while (--n);

            HANDLE hcon = CreateFileW(L"CONIN$", FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);

            if (hcon != INVALID_HANDLE_VALUE) 
            { 
                WriteConsoleInput(hcon, lpBuffer, len, &n); 
                CloseHandle(hcon); 
            }

            delete [] lpBuffer;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...