Hallo, ich starte von meiner C# Anwendung aus eine Eingabeaufforderung, in welche ich über ein WriteLine dann diverse Commandos schreibe. Nun sind die Ausgaben nicht immer gleich lang, womit sich ReadLine aufhängt wenn nichts mehr abzuholen ist bzw. halt auf eine Eingabe in der cmd wartet. Lesen bis Ende funktioniert auch nicht, da ja keins existiert. Der Versuch ein Timeout zu setzen ist daran gescheitert, dass dies cmd nicht unterstützt. Wie wird so was denn klassicherweise gemacht, das problem gibt es ja bestimmt auch noch mit anderen Programmen. Meine Lösungsideen (finde ich jeweils nicht schön): 1. Am Ende ein Sonderzeichen hinterherschicken z.B. ein å (gesprochen o) welches eher nicht in einer Ausgabe zu erwarten ist als bessere Option. 2. Einen zweiten Thread aufmachen, welcher überprüft ob der andere sich aufgehangen hat und evtl. einfach ein beenden Flag setzt und eine neue Zeile erzeugt. 3. Über einen Kill-Thread den anderen vernichten, sollte er sich nicht zurückmelden. Allerdings wird dann die Anfrage sauber aufgelöst? 4. Alle Befehle direkt über C# ausführen, dann aber immer noch nicht sicher das es klappt und nicht wieder der gleiche Effekt auftritt.
Zitat: "Nun sind die Ausgaben nicht immer gleich lang, womit sich ReadLine aufhängt wenn nichts mehr abzuholen ist bzw. halt auf eine Eingabe in der cmd wartet." äääh du meinst Eingang? Zitat: "Lesen bis Ende funktioniert auch nicht, da ja keins existiert." Alles hat ein Ende nur die Wurst hat 2! Ich verstehe irgendwie nicht ganz was du jetzt vor hast, was für Befehle sollen das sein, deine eigenen? Hilft dir vielleicht eine Datei mit der Endung .bat weiter? Ansonsten kannst du ja das Ende eines Strings wenn es mit 0 terminiert ist durch das NULLbyte finden! Es wäre hilfreich, wenn du zeigst wie du deine Eingabeaufforderung mit C# startest!
Meinst Du tatsächlich eine "Eingabeaufforderung", sprich, Du startest "cmd.exe" als neuen Prozess, oder machst Du nur ein Konsolenfenster auf?
@rufus & Skalpell Ja, ich starte wirklich eine cmd.exe von meinem Prozess aus. An eine .bat hatte ich auch schon gedacht, würde es aber lieber ohne machen, stelle ich jetzt mal so ohne Begründung in den Raum. Evtl. wäre es einfach besser alle Programme als Prozess von meinem Programm aus zu starten und nicht den Umweg über cmd zu gehen. Allerdings wurmt es mich auch das nicht sauber umgesetzt zu bekommen. Hier der aufruf vom Programm
1 | System.Diagnostics.Process p = new System.Diagnostics.Process(); |
2 | p.StartInfo.UseShellExecute = false; |
3 | p.StartInfo.FileName = "cmd.exe"; |
4 | p.StartInfo.RedirectStandardOutput = true; |
5 | p.StartInfo.CreateNoWindow = true; |
6 | p.StartInfo.RedirectStandardInput = true; |
7 | p.Start(); |
Einlesen wird dann später mit: Console.WriteLine(p.StandardOutput.ReadLine()); gemacht. Dann führe ich Befehle aus und will immer abfragen ob die erfolgreich waren, wenn nicht, wird irgendwann (in ferner Zukunft) einmal eine E-Mail an mich geschickt. Nun folgende Situation, nicht alle aufgerufenen Programme sind von mir ... Write XXX Data Bytes Verify supertoll succesfull oder so, also drei Zeilen jetzt Fehlermeldung zB Write XX DataByes Verify fehlgeschlagen ... Wenn ich jetzt drei Zeilen auslese bleibt er bei Variante 2 hängen, da er noch auf eine Zeile wartet. Andererseits wenn 4 Zeilen erzeugt würden als Fehlermeldung, würde ich mir auch gerne langfristig 4 schicken und nicht nur 3. Habe auch schon versucht ein Timeout einzustellen, aber das unterstützt die cmd.exe nicht. Schön wäre es ja ob ich auch über cmd.exe die information bekommen könnte, ob das aufgerufenen Programm fertig ist und wieviele Zeilen abzuholen sind. Auch langfristig: Wenn der Prozess eine unerwartete Fehlermeldung bekommt, soll immer ein zweiter Versuch gestartet werden und wenn das auch nicht klappt mit anderen Aufgaben fortgefahren werden. Also auch im Fehlerfall sollte es nicht steckenbleiben.
Der Unwissende schrieb: > Schön wäre es ja ob ich auch über cmd.exe die > information bekommen könnte, ob das aufgerufenen Programm fertig ist und > wieviele Zeilen abzuholen sind. Ruf die doch anstelle der CMD direkt auf, dafür ist die Prozess Klasse doch da, so ist das etwas... äh... ungünstig. Dann kriegst du nämlich u.A. auch den Returncode zurückgeliefert.
Du solltest wirklich kein cmd.exe benutzen, wenn du in Wirklichkeit andere Prozesse starten willst. Welchen Sinn macht denn da der Zwischenschritt cmd.exe? Starte die gewünschten Befehle doch einfach direkt, genau so wie du cmd.exe gestartet hast. Das ist die einzige sinnvolle Variante. Und damit erledigt sich dann auch dein Problem: Es gibt beim Lesen ein Dateiende, nämlich wenn sich der Kindprozess beendet hat. Du kannst dann ganz entspannt einfach lesen bis EOF und gut. Für den unwahrscheinlichen Fall, dass du cmd.exe wirklich ehrlich brauchst (ich wüsste keinen guten Grund, es sei denn du musst mit Benutzereingaben arbeiten, die Features von cmd.exe nutzen, z.B. Umlenkung der Ausgabe, Aliases usw.), starte cmd.exe /c "befehl", damit beendet sich cmd.exe nach der Abarbeitung von "befehl" und du hast wieder ein EOF.
Der Unwissende wenn du eine .bat mit dem inhalt "ping google.com > ret.txt" startest findest du das ergebnis in ret.txt vielleicht hilft das ein bissien. ansonsten gibt es auch http://dotnet-snippets.de/dns/shellexecute-SID1000.aspx und viele viele weitere möglichkeiten ist die cmd.exe denn eine voraussetzung oder kennst du nur keine andere möglichkeit :-)?
Hi also das geht eigntlich schon eig mal deinen ganzn code und schau dir mal genau die process klasse an die bietet viele events
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.