| Autor |
Beitrag |
Trashkid2000
      
Beiträge: 561
Erhaltene Danke: 137
|
Verfasst: So 22.01.12 10:39
Hallo,
ich sitze grade an folgendem Problem: Ich möchte gerne einem Process, der von mir gestartet wird, aber die ganze Zeit über läuft, Befehle schicken und dann das Ergebnis abwarten, was in den StandardOutput geschrieben wird, um es dann auszuwerten. Und das ist das Problem
Denn ich kann nicht WaitForExit benutzen, da der Process ja nicht beendet wird...
Ok, ich bin zwar in der Lage, asynchron den Output zu lesen, aber das nützt mir ja nichts, da es ja wieder ein eigener Thread ist.
Hoffe, das Problem ist verstänndlich rübergekommen und jemand weiß dafür eine Lösung.
LG und schönen Sonntag,
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: So 22.01.12 12:29
Trashkid2000 hat folgendes geschrieben : | | Ok, ich bin zwar in der Lage, asynchron den Output zu lesen, aber das nützt mir ja nichts, da es ja wieder ein eigener Thread ist. |
Und das ist ein Problem, weil...? Geht es um eine GUI und das richtige Marshalling der Antwort auf den UI-Thread?
_________________ >λ=
|
|
Trashkid2000 
      
Beiträge: 561
Erhaltene Danke: 137
|
Verfasst: So 22.01.12 16:28
Hallo Kha,
erstmal Danke für Deine Antwort. Ups, hatte ich vergessen, dass es sich um eine WPF-Anwendung handelt.
Ich poste einfach mal etwas Code:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| private StringBuilder outputDataStringBuilder = new StringBuilder(); public string SendCommand(string command) { Process.BeginOutputReadLine(); outputDataStringBuilder.Clear(); Process.StandardInput.WriteLine(command); Process.CancelOutputRead(); return outputDataStringBuilder.ToString(); }
private void OnOutputDataReceived(DataReceivedEventArgs args) { if (!string.IsNullOrEmpty(args.Data)) outputDataStringBuilder.AppendLine(args.Data); }
private void InitializeAndStartProcess() { var startInfo = CreateProcessStartInfo(); Process = new Process() { StartInfo = startInfo }; Process.OutputDataReceived += (x, y) => { OnOutputDataReceived(y); }; Process.Start(); } | So, also der Process, hier als schlechtes Beispiel die cmd.exe, wird also einmal gestartet. Nun soll über die Methode "SendCommand" z.B. der Befehl dir abgesetzt werden. Und diese Methode soll also so lange warten, bis die cmd alles in den Output geschrieben hat. Und den Output dann zurückgeben. Naja, und nun kehrt also meine Methode sofort zurück (mit einem leeren string), und im Hintergrund wird danach alles schön in den StringBuilder geschrieben.
Ich weiß nicht, wie ich das gebacken kriege, dass ich so lange warte...
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: So 22.01.12 16:47
| Zitat: | | bis die cmd alles in den Output geschrieben hat. |
Wenn das Prozess Ende nicht das Ende des in den Output schreiben markiert was dann? Ein spezieller Text der im Output auftaucht? Dann könnte man den Thread eventuell mit einem AutoResetEvent warten lassen und durch einen entsprechenden Prüfcode in OnOutputDataReceived irgendwann freischalten.
|
|
Trashkid2000 
      
Beiträge: 561
Erhaltene Danke: 137
|
Verfasst: So 22.01.12 17:57
Hmm, stimmt schon.
Irgendwie muss ich den Kram ja eh parsen... aber ich wollte die "SendCommand" so allgemeingültig wie möglich gestalten, und dort nicht irgendeine große Logik wie das Parsen des OutputStreams machen. Das sollte dann an einer anderen Stelle passieren. Dachte, dass es da irgendeinen Marker gibt, der sagt "so, ich bin nun fertig". Aber anscheinend nicht.
Vielen Dank auf jeden Fall!
|
|
Trashkid2000 
      
Beiträge: 561
Erhaltene Danke: 137
|
Verfasst: So 22.01.12 20:23
Hi,
auch wenn ich immer noch an einer Lösung interessiert bin...
Ein Kumpel (für den ich das programmieren soll) meinte gerade, dass sich der Process nach einem Befehl immer beendet. Damit besteht das Problem also nicht mehr, da ich darauf reagieren kann.
Vielen Dank auf jenden Fall an denen, die versucht haben, mir zu helfen!
LG
|
|
C#
      
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: So 22.01.12 20:30
Hey Trashkid,
warum willst du das lesen des Outputs überhaupt asynchron machen wenn du sowieso warten willst? Erledige die Ganze Prozedur doch mit ReadToEnd() dann haste ja deinen kompletten Output. Wenn das nicht geht kannste ja in einer Schleife prüfen, ob was neues dazugekommen ist oder nicht. Und wenn nichts neues dazu gekommen ist kannste ja aus der Schleife springen und dann returnen.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: So 22.01.12 21:07
Trashkid2000 hat folgendes geschrieben : | | auch wenn ich immer noch an einer Lösung interessiert bin... |
Die hat Ralf Jansen doch schon genannt  : Wenn du die zwei Threads synchronisieren willst, brauchst du eine Art Mutex, z.B. eben ein AutoResetEvent. Etwas moderner (vielleicht bei dir sogar angemessener wegen GUI?) als einfach in der Methode zu blocken wäre wahrscheinlich aber die Rückgabe eines Task<string>, sollte sich mit einer TaskCompletionSource implementieren lassen (oder für Bonuspunkte über die Reactive Extensions).
_________________ >λ=
|
|
|