Laden...

externes Consolen Programm starten und steuern

Erstellt von Krumnix vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.540 Views
K
Krumnix Themenstarter:in
129 Beiträge seit 2018
vor 3 Jahren
externes Consolen Programm starten und steuern

Hallo.
Habe ein Konsolen Programm, welches zu einer Robotersteuerung die Verdingung aufbaut und man Daten austauschen kann.
Nun würde ich gerne den Ablauf zur Inbetriebnahme des Roboters automatisieren. Sprich, die im Moment alle händisch eingetippten Befehle durch ein C# Programm nach und in die Konsole übergeben.
Das K-Programm starten ist kein Problem. Es zu verstecken und so auch.
Nun zu meinem Probleme, bzw. wo ich im Moment hänge:

1.
Mit

BatchProcess.StartInfo.RedirectStandardOutput = true;
                BatchProcess.StartInfo.RedirectStandardInput = true;

steuere ich ja die Möglichkeit, die Ausgabe umzuleiten, bzw. die Eingabe.
Da nach dem Starten des Konsolen Programms hier eine Eingabe gewartet wird, "hängt" mein Programm in der Zeile:

textBox_Output.Text = textBox_Output.Text + BatchProcess.StandardOutput.Read();

Wie kann ich die Ausgabe abfangen ohne dass mein Programm hängen bleibt, da die Konsole eine Eingabe erwartet?

2.
Mit

BatchProcess.StandardInput.Write("cd");

würde ich gerne die Befehle in die Konsole geben.
Weiß jetzt nicht, ob es an Problem 1 liegt, dass es nicht weiter funktioniert, oder ob ich was falsch mache?

Jemand einen Tipp für mich?
Danke!

4.931 Beiträge seit 2008
vor 3 Jahren

Läuft dein Code bisher synchron, d.h. die textBox_Output.Text-Teile hast du direkt nach dem Starten des Prozesses in demselben Thread aufgerufen?

Dann sollte dir das Process.OutputDataReceived-Ereignis weiterhelfen (beachte auch BeginOutputReadLine()).
So kannst du dann die Eingaben senden und asynchron die Ausgabe verarbeiten (wohl mittels [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)).

3.170 Beiträge seit 2006
vor 3 Jahren

Hallo,

zusätzlich solltest Du am Ende eines Befehls einen Zeilenumbruch (Environment.NewLine) am Ende mitschicken, denn auf der Konsole wird der Befehl ja auch für gewöhnlich erst durch das Drücken der Enter-Taste ausgelöst.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

K
Krumnix Themenstarter:in
129 Beiträge seit 2018
vor 3 Jahren

Die TextBox hab ich rausgeworfen.

Hab aktuell folgenden Code drin:

Process process = new Process();
                process.StartInfo.FileName = CmdCall;
                process.StartInfo.Arguments = " -i" + IPAddress + " \"VERSION\" ";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                {
                    // Prepend line numbers to each line of the output.
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        output_console = output_console + "\n" + e.Data;
                    }
                });
                process.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
                {
                    // Prepend line numbers to each line of the output.
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        output_console = output_console + "\n" + e.Data;
                    }
                });
                process.StartInfo.CreateNoWindow = true;
                process.Start();

                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

In meinem output_console string steht nix drin.
Lustigerweise jedoch im Ausgabe-Fenster von VS2017.
Was mache ich falsch? Wie bekomme ich die Daten in den String?

16.806 Beiträge seit 2008
vor 3 Jahren

Du kannst doch selbst mit dem Debugger schauen, warum das so ist.
[Artikel] Debugger: Wie verwende ich den von Visual Studio?

K
Krumnix Themenstarter:in
129 Beiträge seit 2018
vor 3 Jahren

Ja, sicher weiß ich das. Macht mich aber nicht schlauer.
Mit dem DataReceivedEventHandler erhalte ich wohl jede Änderung in der Console und schreibe dies dann in den String.

Mit BeginOutputReadline stoße ich dies wohl an.

Wenn ich nun mit F11 durchschalte, dann wird erst beim Schließen meiner Anwendung in den String geschrieben, obwohl schon vorher die Console geschlossen ist.

Warum also schreibt er erst beim Beenden des Programms in den String und nicht beim Schließen des Consolenfensters?

T
2.219 Beiträge seit 2008
vor 3 Jahren

Wie sollen wir dir das sagen können ohne deinen Code zu kennen?
Wo wird dann der String überall verwendet?
Wenn nur in den beiden Events, dann vermutlich weil diese erst am Ende gefeuert werden.
Ansonsten an jeder Stelle, die keiner hier einsehen kann.

Mit dem Debugger wäre dies aber am einfachsten zu prüfen.

Nachtrag:
In der Doku steht übrigens auch der hinweis WaitForExit aufzurufen, damit die Ausgabepuffer geleert werden.
Erst dann dürften auch die Events korrekt gefeuert werden.

Nachtrag 2:
Ebenfalls solltest du, wenn es viele Ausgaben gibt, nicht mit String arbeiten.
Nimm hier lieber, wie im Doku Beispiel, einen StringBuilder.
Sonst wirst du mit viel Speicher um dich, wenn dort viele Ausgaben passieren.

Nachtrag 3:
Ebenfalls solltest du für beide Events eine eigene Methode auslagern.
Da beide Events die gleiche Signatur haben, wird somit kein Code unnötig dubliziert.
Ebenfalls kann man sich leicht durch anonyme Event Methoden ein Speicherloch bauen, wenn man dort Objekte von außen reingibt.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

K
Krumnix Themenstarter:in
129 Beiträge seit 2018
vor 3 Jahren

Danke erstmal für eure Hilfen.

Der string war vorher auch ein stringbuilder. Beides hatte keine Auswirkung.
process.WaitForExit füllte den string auch nicht.

Im Grunde erhalte ich ja was, aber nur im Ausgabe-Fenster in VS nicht in meinen String rein.

Die beiden Events habe ich erstmal für mein Verständnis aufzubauen aus dem Beispiel im Link so verwendet.
Schieb die mal in eine eigene Methode. Melde mich dann wieder.
Danke

4.931 Beiträge seit 2008
vor 3 Jahren

Funktioniert es denn, wenn du das Programm außerhalb vom VS startest?
Der VS-Debugger lenkt die Ausgabe extra in das Ausgabe-Fenster zusätzlich um, damit der Entwickler mehr Informationen erhält (z.B. sinnvoll bei GUI-Projekten mit Debug-Konsolenausgaben).