Низкоуровневый ввод и перенаправление консоли - PullRequest
6 голосов
/ 17 января 2011

Я пытаюсь отправить команды на вход приложения cmd.exe, используя низкоуровневые функции консоли чтения / записи.У меня нет проблем с чтением текста (очисткой) с использованием функций ReadConsole...() и WriteConsole() после подключения к консоли процесса, но я не понял, как написать, например, "dir", и консоль интерпретирует его какотправленная команда.

Вот немного моего кода:

CreateProcess(NULL, "cmd.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
AttachConsole(pi.dwProcessId);

strcpy(buffer, "dir");
WriteConsole(GetStdHandle(STD_INPUT_HANDLE), buffer, strlen(buffer), &charRead, NULL);

STARTUPINFO атрибуты процесса все установлены в ноль, за исключением, конечно, атрибута .cb.

На экране ничего не меняется, однако я получаю Error 6: Invalid Handle, возвращаемое с WriteConsole до STD_INPUT_HANDLE.Если я пишу в (STD_OUTPUT_HANDLE), я получаю dir, написанный на экране, но, конечно, ничего не происходит.Я предполагаю, что SetConsoleMode() мог бы помочь, но я пробовал много комбинаций режимов, но ничего не помогло.Я также создал быстрое консольное приложение, которое ожидает ввода (scanf()) и возвращает все, что входит, не работает.

Я также попытался ввести подсказку scanf(), а затемзаглянуть во входной буфер, используя PeekConsoleInput(), возвращает 0, но массив INPUT_RECORD пуст.

Я знаю, что есть другой способ обойти это, используя WriteConsoleInput() для непосредственного внедрения структурированных событий INPUT_RECORD вконсоль, но это будет слишком долго, мне придется отправлять каждое нажатие на нее.

Надеюсь, вопрос ясен.Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.Спасибо за вашу помощь.

Обновление 1:

Я могу отправить нажатия клавиш процессу cmd, используя WriteConsoleInput() с INPUT_RECORD структурами, однако,AttachConsole иногда выдает ERROR_GEN_FAILURE #31: A device attached to the system is not functioning., и, таким образом, INPUT_RECORD не отправляются (Error 6: Invalid Handle).Sleep(1000) после CreateProcess() до AttachConsole() это решает.Символы dir вводятся автоматически, но я не могу понять, как отправить ключ RETURN:

ir[0].EventType = KEY_EVENT;
ir[0].Event.KeyEvent.bKeyDown = TRUE;
ir[0].Event.KeyEvent.dwControlKeyState = 0;
ir[0].Event.KeyEvent.uChar.UnicodeChar = '\n';
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 = '\n';
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(GetStdHandle(STD_INPUT_HANDLE), ir, 2, &charRead);

WriteConsoleInput возвращает 0, но в консоли ничего не происходит,Я попытался установить SetConsoleMode() на ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT и их комбинацию, но безрезультатно.Однако, если я нажимаю клавишу ввода на клавиатуре, автоматически набирается команда dir (в отличие от тех случаев, когда я просто WriteConsole()), так что я думаю, что я на правильном пути.

Не работаетt SSH отправляет фактические нажатия клавиш и получает фактический экранный буфер (как TAB, и CTRL + C работают CTRL + D)?Я за что-то вроде этого.

Обновление 2:

Я обнаружил проблему с введением команды возврата.Должно быть ir[1].Event.KeyEvent.uChar.AsciiChar = '\r';, то есть \r вместо \n, очень просто.

Кажется, что нет никакого способа использовать WriteConsole() для ввода команд, нужно получить, отправив WriteConsoleInput() INPUT_RECORDs или путем создания каналов (которые не всегда идеальны, но хороши для большинства простых приложений).Одним из больших преимуществ использования WriteConsoleInput() является то, что вы можете отправить VK_UP и VK_DOWN для доступа к истории консоли (если мы в CMD) и VK_TAB для автозаполнения, все последовательности CTRL + _,Клавиши ESC и FUNCTION и даже щелчки мышью.

Более подробная информация здесь: http://msdn.microsoft.com/en-us/library/ms687403%28v=vs.85%29.aspx и множество примеров здесь: http://controllingtheinter.net/forums/viewtopic.php?f=116&t=366

Если у кого-то есть другие отличные идеи, не стесняйтесь делать этов. Спасибо всем, кто заинтересовался этим.Надеюсь, это поможет кому-то в будущем.

1 Ответ

2 голосов
/ 17 января 2011

В данный момент вы пытаетесь записать в свой собственный дескриптор стандартного ввода, а не в процесс cmd.exe.Вам придется проделать гораздо больше работы, чтобы перенаправить дескриптор ввода для этого.Требуется труба.Вот статья KB *1001*, в которой показан шаблонный код.

Кстати: всегда проверьте возвращаемое значение функций API.

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