2011-01-17 12 views
6

Estoy tratando de enviar comandos a la entrada de una aplicación cmd.exe usando las funciones de bajo nivel de lectura/escritura de la consola. No tengo problemas para leer el texto (raspado) usando las funciones ReadConsole...() y WriteConsole() después de haberlo conectado a la consola de proceso, pero no he descubierto cómo escribir, por ejemplo, "dir" y hacer que la consola lo interprete como un comando enviado.Entrada y redirección de consola de bajo nivel

Aquí hay un poco de mi código:

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 atributos del proceso se ajustan a cero, excepto, por supuesto, el atributo .cb.

No hay cambios en la pantalla, sin embargo recibo un Error 6: Invalid Handle devuelto de WriteConsole a STD_INPUT_HANDLE. Si escribo al (STD_OUTPUT_HANDLE), escribo mi dir en la pantalla, pero no ocurre nada. Supongo que SetConsoleMode() podría ser de ayuda, pero he probado muchas combinaciones de modos, nada ayudó. También he creado una aplicación de consola rápida que espera la entrada (scanf()) y repite todo lo que entra, no funcionó.

También intenté tipear en el mensaje scanf() y luego echar un vistazo en el búfer de entrada usando PeekConsoleInput(), devuelve 0, pero la matriz INPUT_RECORD está vacía.

Soy consciente de que hay otra forma de evitar esto usando WriteConsoleInput() para inyectar directamente eventos estructurados INPUT_RECORD en la consola, pero esto sería demasiado largo, tendré que enviar cada pulsación de tecla en él.

Espero que la pregunta sea clara. Por favor, avíseme si necesita más información. Gracias por tu ayuda.

Actualización 1:

soy capaz de enviar pulsaciones de teclas a un proceso cmd usando WriteConsoleInput() con INPUT_RECORD estructuras, sin embargo, el AttachConsole veces lanza ERROR_GEN_FAILURE #31: A device attached to the system is not functioning., y por lo tanto la INPUT_RECORD no se envían (Error 6: Invalid Handle). Sleep(1000) después de CreateProcess() antes de AttachConsole() resuelve esto. Los personajes dir se escriben en forma automática, pero no puedo encontrar la manera de enviar la clave 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 vuelve 0, pero no pasa nada en la consola, He tratado de establecer SetConsoleMode() a ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT y una combinación de los mismos, sin resultados, sin embargo. Sin embargo, si presiono enter desde el teclado, se ejecuta el comando dir de escritura automática (a diferencia de los tiempos en los que simplemente WriteConsole()), así que supongo que estoy en el camino correcto.

¿No envía SSH las pulsaciones de tecla reales y obtiene el búfer de pantalla real (como TAB y CTRL + C CTRL + D)? Estoy buscando algo así.

Actualización 2:

he encontrado el problema con la inyección del comando de retorno. Debería haber sido ir[1].Event.KeyEvent.uChar.AsciiChar = '\r';, es decir, \r en lugar de \n, super simple.

Parece que no hay manera de utilizar WriteConsole() a los comandos de entrada, se debe llegar a funcionar mediante el envío de WriteConsoleInput() INPUT_RECORDs o creando tubos (que no siempre son perfectas, pero grande para la mayoría de aplicaciones recta hacia adelante). Una gran ventaja de usar WriteConsoleInput() es que puede enviar VK_UP y VK_DOWN, para acceder al historial de la consola, (si estamos en CMD) y VK_TAB para autocompletar, todas las secuencias CTRL + _, teclas ESC y FUNCTION e incluso MOUSE CLICKS .

Más información aquí: http://msdn.microsoft.com/en-us/library/ms687403%28v=vs.85%29.aspx toneladas, además de ejemplos aquí: http://controllingtheinter.net/forums/viewtopic.php?f=116&t=366

Si alguien tiene otras ideas se sienten libres para hacer mella en Gracias a todos los que tomaron interés en esto.. Espero que esto ayude a alguien en el futuro.

Respuesta

2

Ahora está intentando escribir en su propio controlador stdin, no en el del proceso cmd.exe. Tendrás que trabajar mucho más para redirigir el identificador de entrada para ese. Requiere una tubería. Aquí hay un KB article que muestra el código repetitivo.

Btw: siempre compruebe el valor de retorno de las funciones de la API.

+0

Pensé en adjuntarme a la consola del nuevo proceso. 'AttachConsole()' permite esto; cuando 'printf() 'después de adjuntar estoy imprimiendo en' cmd.exe'. He actualizado el código de error que obtuve de 'WriteConsole()' a 'STD_INPUT_HANDLE' – soulseekah

+0

Solo compartes la ventana de la consola, eso es todo. Sí, el código de error muestra lo que está pasando, no puede escribir en un identificador de entrada. –

+0

He leído ese código y lo probé ayer, funciona como un encanto, por desgracia, los programas generados como 'FTP.exe' y' EDIT.exe' tienen sus propios búferes, que no son redirigidos, esto requiere un nivel bajo de lectura y escritura a la consola. Básicamente, quiero clonar una ventana de consola redirigiendo todo de uno a otro. – soulseekah

Cuestiones relacionadas