低级控制台输入和重定向

sou*_*kah 6 c windows console winapi

我正在尝试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);
Run Code Online (Sandbox Code Playgroud)

STARTUPINFO除了.cb属性之外,进程的属性都被设置为零.

在屏幕上没有什么变化,但是我发现了一个Error 6: Invalid Handle从返回WriteConsoleSTD_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);
Run Code Online (Sandbox Code Playgroud)

WriteConsoleInput回报0,但什么也没有发生在控制台中,我试过设置SetConsoleMode()ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT及其组合,没有结果,虽然.但是,如果我从键盘按Enter键,则会dir执行自动键入的命令(与我刚刚执行的时间不同WriteConsole()),所以我猜我正处于正确的轨道上.

SSH是否通过实际的按键发送并获取实际的屏幕缓冲区(如TAB和CTRL + C CTRL + D工作)?我追求的是类似的东西.

更新2:

我发现注入return命令的问题.应该是ir[1].Event.KeyEvent.uChar.AsciiChar = '\r';一个\r而不是一个\n,超级简单.

似乎没有办法使用WriteConsole()输入命令,应该通过发送WriteConsoleInput()INPUT_RECORD或创建管道(这并不总是完美的,但对大多数直接应用程序来说很好).使用的一个巨大优势WriteConsoleInput()是,您可以发送VK_UPVK_DOWN访问控制台历史记录(如果我们在CMD中)和VK_TAB自动完成,所有CTRL + _序列,ESC和FUNCTION键甚至是MOUSE CLICKS.

更多信息请访问:http://msdn.microsoft.com/en-us/library/ms687403%28v=vs.85%29.aspx此处 还有大量示例:http://controllingtheinter.net/forums/viewtopic.php ?F = 116&T = 366

如果有人有其他伟大的想法,请随时插入.感谢所有对此感兴趣的人.希望这可以帮助将来的某个人.

Han*_*ant 3

现在,您正在尝试写入自己的标准输入句柄,而不是 cmd.exe 进程的标准输入句柄。您必须做更多的工作来重定向该输入句柄。它需要一个管道。这是一篇显示样板代码的知识库文章。

顺便说一句:始终检查 API 函数的返回值。