ShellExecute & Co. zum XXX. Mal
-
Hallo zusammen,
ich habe zwar in der FAQ und in diesem Forum schon einige Beiträge zu dem Thema gefunden aber an einer Stelle komm ich trotzdem nich weiter.
Mein Aufruf sieht wie folgt aus:
ShellExecute((HWND)this,"open","plink", "-l xxx ..etc...", NULL, SW_MINIMIZE)
Damit stelle ich eine Verbindung zu einem SSH-Server her. Danach habe ich eine offene Dos-Box in der ich als User auf dem Server angemeldet bin:
xxx@yyy:~#
Jetzt möchte ich wenn nötig die Verbindung wieder trennen können indem ich an diese Stelle "exit" schreibe.
Allerdings wenn ich jetzt das hier mache:
ShellExecute((HWND)this,"open","exit", NULL, NULL, SW_MINIMIZE)
öffnet sich eine neue Dos-Box, schreibt "exit" und schließt sich wieder. Die erste Dos-Box bleibt davon unberührt. Ich will diese Dos-Box aber auch nich einfach schließen wie in der FAQ erklärt.
Kann ich mir irgendwie ein Handle auf die Dos-Box holen und ShellExecute oder Ähnlichem sagen: Schreibe in Dos-Box Nr 1 ???
Vielen Dank schonmal!!!
Tody
-
Mit ShellExecute kommst du da nicht weiter.
Aber ich glaube hiermit. Ist aber etwas komplizierter.
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q190/3/51.asp&NoWebContent=1
-
@ f, also so ganz steige ich da nicht durch aber danke trotzdem!
Ich hab jetzt mal ausprobiert ShellExecuteEx zu benutzen. Da bekommt man ja den hProcess.
Es läuft wohl doch darauf raus, dass ich den Prozess beende ohne einen Logout mit exit zu machen?!
Mit GetExitCodeProcess und dem hProcess bekomme ich doch den ExitCode. Und dann kann ich ExitProcess aufrufen!?
Jetzt weiß ich nur nicht wie ich das Ergebnis (LPDWORD) von GetExitCodeProcess in ExitProcess benutze. Da wird ein UINT benötigt.Oder bin ich hier völlig auf dem Holzweg???
-
kannst du ihn nicht einfach casten?
-
ich mache folgendes:
if(sei.hProcess) { LPDWORD code; GetExitCodeProcess(sei.hProcess, code); ExitProcess((UINT)code); CloseHandle(sei.hProcess); }
sei ist vom Typ SHELLEXECUTEINFO
ShellExecute wurde aufgerufenIch bekomme beim Erstellen 2 Warnungen:
Typumwandlung: Zeigerverkürzung von LPDWORD zu UINT
Die Variable code wurde ohne Initialisierung übernommenIch glaub ich bring da was durcheinander. LPDWORD ist doch ein 32Bit signed Integer und UINT spricht wohl für sich.
Und der Parameter lpExitCode von GetExitCodeProcess ist doch ein Ausgabeparameter. Was muss ich da vorher initialisieren?Wenn ich debugge, hängt er an der Stelle mit der nicht initialisierten Variablen code.
-
Versuch's mal so:
if(sei.hProcess) { DWORD code; GetExitCodeProcess(sei.hProcess, &code); ExitProcess((UINT)code); CloseHandle(sei.hProcess); }
-
klar sollte ja ein Pointer rein. wer lesen kann...
naja mir sind da so manche Sachen nicht klar.Allerdings löst sich jetzt mein MFC_Prog in Luft auf und die DOS-Box bleibt nach wie vor da.
Auf jeden Fall vielen Dank schonmal!
Tody
-
Öhm... ExitProcess beendet DEINEN PROZESS!
Was Du dort tust, ist den Status des DOS-Prozesses abfragen (wird STILL_ACTIVE sein) und beendest dann deinen eigenen Prozeß mit Exitcode STILL_ACTIVE...
-
@hepi
dann habe ich wohl wieder nich ganz aufgepasst.ich dachte damit beende ich den dos-prozess. darum geht es mir ja. dass ich mit buttonA ein shellexecute ausführe und mit buttonB diese dadurch entstandene dos-box wieder schließe, bzw. das programm beende welches in der dos-box läuft.
sowas muss doch möglich sein.
ich stelle mit das so vor:
buttonA:
shellexecute("Programm-Start", SW_HIDE);buttonB:
shellexecute("Programm-Stop", AusführenInVerstecktemFenster);aber beides spielt sich in der selben dos-box ab.
außerdem wenn ich ein programm gestartet habe, muss ich es erst beenden bevor ich ein neues starten kann. aber das hab ich schon hingekriegt.
vielleicht weiß ja jemand nen lösungsansatz?!
danke schonmal für alle antworten!
tody
-
Dazu brauchst du dann Pipes um stdout und stdin umzubiegen. Ich empfehle dir mal hier zu suchen. Da gibts den Einen oder Andere Beitrag dazu.
-junix
-
@junix
danke für den tip! zu diesem thema hat mir <f> glaub ich auch nen link gepostet. is allerdings noch etwas verwirrend für mich.ich hab mal nach "pipe" gesucht und mir aus den suchergebnissen ein beispiel rausgepickt.
das führt einen createprocess aus. zum beispiel nen ping. das ergebnis wird dann in ner messagebox ausgegeben.
wenn ich das jetzt richtig verstanden habe, ist da jetzt eine pipe mit der ich daten von der dos-konsole empfangen kann. output oder input? aus welcher richtung is das zu sehen?wenn ich jetzt einen befehl an diese dos-konsole senden will, brauche ich jetzt ne zweite pipe, oder?
da kommt noch eine schleife drin vor, bei der ich ein problem sehe:
GetExitCodeProcess(pi.hProcess,&retCode); while (retCode==STILL_ACTIVE) { GetExitCodeProcess(pi.hProcess,&retCode); }
wenn ich plink mit parametern aufrufe findet eine ssh-login statt. danach habe ich den prompt da stehen:
user@machine:~#
das heißt, dass mein returncode immer STILL_ACTIVE sein wird. da ja der prozess noch läuft und eine eingabe erwartet. an dieser stelle will ich ja beim klick auf einen button "exit" schreiben und das wars.
ich nehm am besten diese schleife mal raus.
-
Du musst 2 Pipes eröffnen: Eine die aus Sicht des Konsolenprogramms stdin darstellt (da kannst du reinschreiben mit WriteFile und das programm glaubt, das sind Tastenanschläge) und eine die stdout darstellt (Da wird der Text des Programms ausgegeben)
-junix
-
Vielleicht hilft dir aus das hier aus den FAQ und ggf. WaitForSingleObject
-
hallo!
wollte mich nur bedanken für die hilfe!
mit etwas rumprobieren und der msdn habe ich in etwa rausgefunden wie die pipes funktionieren. ich hoffe ich krieg es jetzt alleine hin.
das beispiel aus der msdn hat mir ziemlich geholfen:
[url] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/creating_a_child_process_with_redirected_input_and_output.asp [/url]also danke an alle!
gruß
tody
-
War ja auch gar nicht schwer, nichtwahr? (o; Hatte erst auch meine Mühe aber dann... (o;
-junix
-
@junix
es war etwas schwerer als fahrradfahren aber es hielt sich in grenzen.
frauen verstehen is schwerer. ;o))))trotzdem habe ich wieder ein kleines problem. ich hab das ganze in ner win32-anwendung probiert. allerdings wollte ich es dann in mein mfc-projekt einbauen und da startet zwar auf button-klick der prozess aber dann steht meine mfc-anwendung still. ich kann dann keinen button mehr klicken. es wird irgendwie auf ne eingabe in der konsole gewartet.
hat da jemand ne idee???
danke
tody
-
Stand vor dem Selben Problem. Bei mir wars so, dass ReadFile() immer gewartet hat, bis der angeforderte Buffer gefüllt wurde.
Deshalb habe ich dann mit PeekNamedPipe() zunächst die Anzahl Bytes in der Pipe ausgelesn und dann gezielt einen ReadFile() mit der Anzahl Bytes ausgeführt. Das Ganze dann in einer Schleife und zwischen jedem neuen PeekNamedPipe() kam dann wieder eine kleine Routine, welche die Message-Queue (Peekmessage, etc.) abgearbeitet hat.
-junix
-
Was ich vergass: Witzig am Ganzen ist die Tatsache, dass PeekNamedPipe auch unter Windows Playstation-Series (DOS-Basierende Linie) unterstützt ist. Und das obwohl diese Systeme gar keine Named-Pipes unterstützen? Naja, Microsoft war noch nie für Konsistenz berühmt...
-junix
-
*LOL*
Danke schonmal für die Tips. Ich geb mich mal ran.
Aber erstmal mach ich Mittagspause!
-
also hier hänge ich. hab nich ganz verstanden warum er sich bei ReadFile aufhängt. Hängt das damit zusammen, dass ReadFile vielleicht weniger Zeichen liest als ich angegeben hab. Und danach will ReadFile noch weiterlesen bis zu der Anzahl Zeichen, die ich angegeben hab obwohl schon nix mehr in der Pipe steht. (Ich hoffe man versteht was ich meine)
Ich hab auf jeden Fall diese Methode hier, in der ich aus der Pipe lese. BUFSIZE = 4096
BOOL ReadFromPipe() { DWORD dwRead, dwPeekRead, dwWritten, dwAvailable; CHAR chBuf[BUFSIZE]; PeekNamedPipe(hOutReadDpl,chBuf, BUFSIZE, &dwPeekRead, &dwAvailable, NULL); if (dwPeekRead != 0) { // Read output from the child process, and write to parent's STDOUT. ReadFile( hOutReadDpl, chBuf, dwPeekRead, &dwRead, NULL); WriteFile(hStdOut, chBuf, dwRead, &dwWritten, NULL); } return 0; }
in einer win32 funktioniert der Code. Aber in meinem MFC-Prog ist dwPeekRead immer 0.
@junix
den Rest von wegen in Schleife und so weiter habe ich nicht richtig verstanden. Ich bin noch nicht so fit.