Konsolenprgramm steuern (stdin)
-
Hallo,
ich habe ein altes DOS- Programm, das unter WinXP in der Konsole (cmd) läuft. Jetzt möchte ich dieses Programm von meinem VC++ Programm aus starten und das DOS- Programm bedienen, also Texte schreiben oder F- Tasten simulieren.Ich lege eine Pipe an (CreatePipe), starte den Prozess mit CreateProcess und schreibe mit WriteFile in die Pipe.
Was muss ich tun, damit das DOS- Programm, das nichts von der Pipe weiss, diese Eingaben auch annimmt/ anzeigt?
Mit dem folgenden Programm kann ich den Prozess starten und in die Pipe schreiben, allerdings kommt nichts an.
void CShellViewDlg::OnCreate() { SECURITY_ATTRIBUTES sa; ZeroMemory(&sa,sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; //TODO //sichern des Handles hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); HANDLE hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); //Pipe anlegen if(!CreatePipe(&hChildStdinRd, &hChildStdinWr, &sa,0)){ MessageBox("Fehler beim Pipe- Erzeugen"); } if(!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)){ MessageBox("Fehler bei Verbindung zu Stdin"); } //Duplizieren des Schreib Handels, damit es nicht vererbt wird if(!DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0,FALSE, DUPLICATE_SAME_ACCESS)){ MessageBox("Fehler beim Duplizieren"); } CloseHandle(hChildStdinWr); /******************************************************************** ********** Prozess starten ********************************** ********************************************************************/ STARTUPINFO si; ZeroMemory(&si,sizeof(STARTUPINFO)); // stdin, stdout und stderr des Kindes in STARTUPINFO eintragen si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = hChildStdinRd; si.hStdOutput = hChildStdoutWr; si.hStdError = hChildStdoutWr; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); GetStartupInfo(&si); BOOL ret = CreateProcess(NULL,"C:\\WINNT\\System32\\cmd.exe",// Name der Appl &sa, // Default process security attributes NULL, // Default thread security attributes TRUE, // inherit handles from the parent 0, // Normal priority NULL, // Use the same environment as the parent NULL, // Launch in the current directory &si, // Startup Information &pi); // Process information stored upon return if(ret){ int dwProcessId = pi.dwProcessId; char final_string[200]; sprintf(final_string, "ProzessId: %i", dwProcessId); MessageBox(final_string); //Beendet den Prozess // HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE,dwProcessId ); // TerminateProcess (hProcess,0); // CloseHandle(hProcess); } else { MessageBox("Fehler beim Erzeugen des Prozesses"); } } //in die Pipe schreiben void CShellViewDlg::Write(HANDLE childStdinWrDup) { LPCTSTR line = "Test von Stdin"; DWORD dwWritten; if(!WriteFile(childStdinWrDup, line, _tcslen(line)*sizeof(TCHAR),&dwWritten,NULL)){ MessageBox("Fehler beim Schreiben"); } else{ char final_string[200]; sprintf(final_string, "Länge des geschriebenen Textes: %i", dwWritten); MessageBox(final_string); } } // void CShellViewDlg::OnWrite() { Write(hChildStdinWrDup); }
gruss
ziba
-
Hi, erstmal Willkommen im Forum.
Kannst du deinen Code bitte in [ cpp ] [ /cpp ] - Tags (ohne Leerzeichen) schreiben? Dann wird der Code übersichtlicher angezeigt.
-
Kennst du den Artikel schon:
http://support.microsoft.com/default.aspx?scid=kb;en-us;190351
-
Danke erstmal für die Antwort.
Hab mir den Artikel bei MSDN durchgelesen und das Programm mal getestet.
Kann sein, dass ich's nur grad nicht blicke, aber
bei diesem Beispielprogramm schickt der Kindprozess ja die Daten zurück, die der Vaterprozess gesendet hat.
Bei meinem Programm müsste der Kindprozess die Daten, die der Vater sendet im eigenen Fenster anzeigen. Mein Problem ist, dass ich vom DOS- Programm nur ein exe- File habe, also den Code nicht verändern kann. Ich bräuchte also genau die Schnittstelle, die die Tastatur nutzt.gruss
ziba
-
Noch eine Frage:
Mit
si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = hChildStdOut; si.hStdInput = hChildStdIn; si.hStdError = hChildStdErr;
lege ich die STARTUPINFO des Kindprozesses fest. si.dwFlags = STARTF_USESTDHANDLES; legt fest, dass die nachfolgenden 3 Parameter für Stdout, Stdin und Stderr des Kindes verwendet werden.
Soweit so gut, aber ich möchte, dass der Kindprozess nur den Stdin vom Vaterprozess bekommt und der Stdout bleibt, wie er ist. Also wie komme ich an den Stdout des Kindprozesses, oder wie muss si.hStdOutput = ??? aussehen, damit der Kindprozess seinen Stdout behält. Parameter weglassen oder gleich NULL setzen hilft nicht.
-
Hab das Programm zum Laufen bekommen und leicht abgeändert, sodass ich es auch für ein eigenes Konsolenprogramm nutzen kann.
Mit nem normalen Konsolenprogramm funktioniert das auch ganz gut, aber wenn ich mein altes DOS- Programm starte bekomme ich nur folgende Fehlermeldung:Titel: 16-Bit-MS-DOS-Teilsystem
D:\...\...\yyy.exe
Die NTVDM-CPU hat einen ungültigen Befehl entdeckt.
CS:0836 IP:01f2 OP:63 65 73 73 2e Klicken Sie auf "Schließen" ...Kann sich jemand vorstellen, warum das jetzt kommt.
Es muss doch einen Weg geben, das Programm zu steuern.
Mit dem TOOL von autoitscript.com gehts ja auch.