2011-01-17 7 views
6

Próbuję wysyłać polecenia do wejścia aplikacji cmd.exe przy użyciu funkcji konsoli odczytu/zapisu niskiego poziomu. Nie mam problemu z odczytaniem tekstu (skrobanie) przy użyciu funkcji ReadConsole...() i WriteConsole() po dołączeniu do konsoli procesu, ale nie mam pojęcia, jak napisać na przykład "dir" i czy konsola interpretuje je jako wysłane polecenie.Niski poziom wejścia i przekierowania konsoli

Oto nieco mojego kodu:

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 atrybuty procesu wszystkie są ustawione na zero, z wyjątkiem, oczywiście, atrybut .cb.

Nic nie zmienia się na ekranie, jednak otrzymuję numer Error 6: Invalid Handle zwrócony z WriteConsole na STD_INPUT_HANDLE. Jeśli napiszę na numer (STD_OUTPUT_HANDLE), na ekranie wyświetli się napis dir, ale nic się nie dzieje. Zgaduję, że pomocna może być SetConsoleMode(), ale wypróbowałem wiele kombinacji trybów, nic nie pomogło. Stworzyłem także szybką aplikację konsolową, która czeka na dane wejściowe (scanf()) i odtwarza echo z powrotem, niezależnie od tego, co wchodzi, nie działa.

Próbowałem również wpisywać w monitach scanf(), a następnie zajrzeć do bufora wejściowego za pomocą PeekConsoleInput(), zwraca 0, ale tablica INPUT_RECORD jest pusta.

Jestem świadomy, że istnieje inny sposób obejścia tego przy użyciu WriteConsoleInput() do bezpośredniego wstrzykiwania strukturalnych zdarzeń INPUT_RECORD do konsoli, ale to byłoby zbyt długie, będę musiał wysłać każde naciśnięcie klawisza do niego.

Mam nadzieję, że pytanie jest jasne. Proszę dać mi znać, jeśli potrzebujesz więcej informacji. Dzięki za pomoc.

Aktualizacja 1:

Jestem w stanie wysłać keypresses do cmd procesu z wykorzystaniem WriteConsoleInput() z INPUT_RECORD konstrukcjom jednak AttachConsole czasami rzuca ERROR_GEN_FAILURE #31: A device attached to the system is not functioning., a tym samym nie są wysyłane INPUT_RECORD (Error 6: Invalid Handle). Sleep(1000) po CreateProcess() rozwiązuje to przed AttachConsole(). Znaki dir są wpisane automatycznie, ale nie mogę dowiedzieć się, jak wysłać klucz 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 powraca 0, ale nic się nie dzieje w konsoli Próbowałem ustawienie SetConsoleMode() do ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT oraz Kombinacja tego, bez rezultatów. Jeśli jednak naciśniesz enter z klawiatury, automatycznie wpisane polecenie dir wykona (w przeciwieństwie do czasów, kiedy po prostu WriteConsole()), więc myślę, że jestem na dobrej drodze.

Czy SSH nie przesyła rzeczywistych naciśnięć klawiszy i nie pobiera rzeczywistego bufora ekranu (np. TAB, CTRL + C CTRL + D)? Po coś podobnego.

Aktualizacja 2:

, że okazało się, że problemy ze wstrzykiwaniem polecenie powrotu. Powinien być bardzo prosty w porównaniu z ir[1].Event.KeyEvent.uChar.AsciiChar = '\r';, to jest \r zamiast z \n.

Wydaje się, że nie ma możliwości korzystania z WriteConsole() do poleceń wejściowych, trzeba dostać się poprzez wysłanie WriteConsoleInput() INPUT_RECORDs lub tworząc potoków (które nie zawsze są idealne, ale doskonale nadaje się do większości zastosowań prosto do przodu). Jedną wielką zaletą używania WriteConsoleInput() jest to, że można wysyłać VK_UP i VK_DOWN, aby uzyskać dostęp do historii konsoli (jeśli jesteśmy w CMD) i VK_TAB do automatycznego uzupełniania, wszystkie sekwencje CTRL + _, klawisze ESC i FUNCTION, a nawet klawisze MYSZY .

Więcej informacji tutaj: http://msdn.microsoft.com/en-us/library/ms687403%28v=vs.85%29.aspx plus ton przykładów tutaj: http://controllingtheinter.net/forums/viewtopic.php?f=116&t=366

Jeśli ktoś ma inne wielkie idee krępuj się chip Dziękujemy wszystkim, którzy wzięli w tym interes.. Mam nadzieję, że to pomoże komuś w przyszłości.

Odpowiedz

2

W tej chwili próbujesz napisać do własnego uchwytu stdin, a nie do procesu cmd.exe. Będziesz musiał znacznie więcej pracy, aby przekierować uchwyt wejściowy dla tego. Wymaga rury. Oto KB article, który pokazuje kod na płycie głównej.

Btw: zawsze sprawdź wartość zwracaną funkcji API.

+0

Myślałem, że dołączam do konsoli nowego procesu. 'AttachConsole()' pozwala na to; kiedy 'printf()' po dołączeniu faktycznie drukuję do 'cmd.exe'. Zaktualizowałem kod błędu, który otrzymałem od 'WriteConsole()' do 'STD_INPUT_HANDLE' – soulseekah

+0

Udostępniasz tylko okno konsoli, to wszystko. Tak, kod błędu pokazuje, co dzieje się źle, nie możesz pisać do uchwytu wejściowego. –

+0

Przeczytałem ten kod i wypróbowałem go wczoraj, działa jak urok, niestety takie programy spawnowane jak 'FTP.exe' i' EDIT.exe' mają własne bufory, które nie są przekierowywane, to wymaga niskiego poziomu odczytu i zapisu do konsoli. Zasadniczo chcę sklonować okno konsoli, przekierowując wszystko od jednego do drugiego. – soulseekah

Powiązane problemy