Forum: PC-Programmierung C# Konsolenanwendung über GUI steuern


von Pascal H. (pase-h)


Lesenswert?

Hallo,
ich habe folgendes Problem:
Ich habe hier eine .Bat Datei, welche einen Minecraft Server Startet. 
Jedoch funktioniert das zwecks den ganzen benötigten Plugins nur über 
die Windows Konsole. Nun möchte ich mir ein GUI in Visual C# 
zusammenstellen, worüber ich den Server Steuern kann.


Nur mal so zum Vorstellen, was ich vorhabe:
Um einen Spieler zu kicken, muss ich
/kick Player
eintippen.
Ich möchte aber per Listbox den Player auswählen, und ihn dann per 
Knopfdruck kicken können.
Ich müsste also zuerst mit
1
/list
eine Spielerliste ausgeben lassen und die Spieler auf der Liste in eine 
Listbox einfügen. Als nächstes bräuchte ich dann einen Button, welcher 
dann in die Konsole
1
/kick + den Inhalt der Listbox
schreibt.

So nun meine Frage:
Wie kann ich über eine Windows Form, in Visual C# die Konsolenanwendung 
Steuern?

Zum Schluss noch der Inhalt der Start.bat:
1
@ECHO OFF
2
SET BINDIR=%~dp0
3
CD /D "%BINDIR%"
4
"%ProgramFiles(x86)%\Java\jre6\bin\java.exe" -Xms1024M -Xmx1024M -jar craftbukkit.jar
5
list
6
PAUSE

Mfg
pase-h

von Peter II (Gast)


Lesenswert?

du musst das Programm mit CreateProcess (oder bei .net mit der Process 
Klasse) starten und musst dich mit dem dem Standardinput und den 
Standardoutput verbinden. Dann kannst du einfach die Befehle den dem 
Stream schreiben und auch die Antwort von dort aus lesen.

von Pascal H. (pase-h)


Lesenswert?

Danke für den Hinweis mit Standardinput/Output.
Jedoch habe ich noch eine Frage:
Wie kann ich einen Endlosstream zum Lesen machen, dass mir jede 
Consolenmeldung in Echtzeit angezeigt wird?

Zurzeit wird der Prozess über einen Button mit folgendem Code gestartet:
1
            Process myProcess = new Process();
2
            ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(@"J:\Users\Pascal\Desktop\Minecraft Server\START.BAT");
3
            myProcessStartInfo.UseShellExecute = false;
4
            myProcessStartInfo.RedirectStandardOutput = true;
5
            myProcess.StartInfo = myProcessStartInfo;
6
            myProcess.Start();
7
            
8
            StreamReader myStreamReader = myProcess.StandardOutput;
9
            // Read the standard output of the spawned process.
10
11
            string myString = myStreamReader.ReadLine();
12
            Reader.Text += myString + "\r\n";

Wenn ich es mit
1
string myString = myStreamReader.ReadLine();
versuche, dann hängt sich die ganze Anwendung auft, und ich bekomme den 
Folgenden Output, wenn ich die Konsole wieder geschlossen habe:
1
151 recipes
2
16 achievements
3
>
4
>
5
...
6
>
7
>
8
Batchvorgang Beenden? (J/N)

Die ersten beiden Zeilen werden Korrekt ausgelesen, danach werden leider 
nur noch ">" angezeigt.

Ich hoffe ihr könnt mir helfen
Mfg
pase-h

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Also erst mal würde ich die BATCH Datei vergessen die ist völlig unnötig 
und macht die Sache nur kompliziert.

Was das Batchfile macht ist einfach nur das Arbeitsverzeichnis auf 
BinDir zu setzen (kannst du dir mit echo Ausgeben lassen was für einen 
Wert das hat) und dann die JVM mit einem JAR aufzurufen. Das Verhalten 
solltest du nachbilden.

Als nächstes musst du dann in einem eigenem Thread den Standardouput 
lesen, und deine Befehler per Standardinput eingeben, zum Testen würd es 
wohl sowas tun wie:
1
while(true) {
2
 cout << myStreamReader.ReadLine() << endl;
3
}

Die > sind höchstwahrscheinlich die Aufforderung zur Eingabe eines 
Befehls.

von Arc N. (arc)


Lesenswert?

Das MSDN-Beispiel etwas erweitert...
1
    Process proc = new Process()
2
    
3
    proc.StartInfo.FileName =  "abcd.exe";
4
5
    // u.U. noch das 
6
    proc.StartInfo.WorkingDirectory = "dir";
7
    // setzen und die 
8
    proc.StartInfo.EnvironmentVariables.Add("BINDIR", "dir");
9
    // einstellen und ganz auf die Batch-Datei verzichten
10
11
    proc.StartInfo.UseShellExecute = false;
12
    proc.StartInfo.RedirectStandardInput = true;
13
    proc.StartInfo.RedirectStandardOutput = true;
14
    proc.StartInfo.RedirectStandardError = true;
15
    proc.EnableRaisingEvents = true;
16
    proc.StartInfo.CreateNoWindow = true;
17
18
    proc.ErrorDataReceived += ProcessDataReceived;
19
    proc.OutputDataReceived += ProcessDataReceived;
20
21
    proc.Start();
22
23
    proc.BeginErrorReadLine();
24
    proc.BeginOutputReadLine();
25
26
     proc.WaitForExit();
27
28
     // event handler -> hier kommen die Ausgaben des Programms an
29
     // Eingaben an das Programm z.B. so 
30
     // proc.StandardInput.WriteLine("command"); 
31
32
     void ProcessDataReceived(object sender, DataReceivedEventArgs e) {
33
        if (e.Data != null) {
34
        }
35
    }

http://msdn.microsoft.com/de-de/library/system.diagnostics.processstartinfo.redirectstandardoutput.aspx

von Pascal H. (pase-h)


Lesenswert?

Arc Net schrieb:
> Process proc = new Process()
>
>     proc.StartInfo.FileName =  "abcd.exe";
>
>     // u.U. noch das
>     proc.StartInfo.WorkingDirectory = "dir";
>     // setzen und die
>     proc.StartInfo.EnvironmentVariables.Add("BINDIR", "dir");
>     // einstellen und ganz auf die Batch-Datei verzichten
>
>     proc.StartInfo.UseShellExecute = false;
>     proc.StartInfo.RedirectStandardInput = true;
>     proc.StartInfo.RedirectStandardOutput = true;
>     proc.StartInfo.RedirectStandardError = true;
>     proc.EnableRaisingEvents = true;
>     proc.StartInfo.CreateNoWindow = true;
>
>     proc.ErrorDataReceived += ProcessDataReceived;
>     proc.OutputDataReceived += ProcessDataReceived;
>
>     proc.Start();
>
>     proc.BeginErrorReadLine();
>     proc.BeginOutputReadLine();
>
>      proc.WaitForExit();
>
>      // event handler -> hier kommen die Ausgaben des Programms an
>      // Eingaben an das Programm z.B. so
>      // proc.StandardInput.WriteLine("command");
>
>      void ProcessDataReceived(object sender, DataReceivedEventArgs e) {
>         if (e.Data != null) {
>         }
>     }

zu dem Codeausschnitt hätte ich noch ein paar Fragen:
Mit
>     proc.StartInfo.FileName =  "abcd.exe";
>
>     // u.U. noch das
>     proc.StartInfo.WorkingDirectory = "dir";
>     // setzen und die
>     proc.StartInfo.EnvironmentVariables.Add("BINDIR", "dir");
>     // einstellen und ganz auf die Batch-Datei verzichten
wird doch die Batchdatei ersetzt?
Nur wie Starte ich java mit den benötigten parametern ->
1
"%ProgramFiles(x86)%\Java\jre6\bin\java.exe" -Xms1024M -Xmx1024M -jar craftbukkit.jar


Bei "dir" →
>     proc.StartInfo.WorkingDirectory = "dir";
 muss ich quasi das Verzeichnis eintragen, wo die craftbukkit.jar ist, 
da diese im Server Hauptverzeichnis liegt, wo alle Plugins/wichtige 
Daten sind.

Nur bei dieser Zeile bin ich mir jetzt nich ganz sicher:
>     proc.StartInfo.EnvironmentVariables.Add("BINDIR", "dir");
was muss ich bei "BINDIR" eintragen, und muss in "dir" das gleiche wie 
in
>     proc.StartInfo.WorkingDirectory = "dir";
?

Mfg
pase-h

von Arc N. (arc)


Lesenswert?

Pascal H. schrieb:
> Nur wie Starte ich java mit den benötigten parametern ->

proc.StartInfo.Arguments

>
1
> "%ProgramFiles(x86)%\Java\jre6\bin\java.exe" -Xms1024M -Xmx1024M -jar
2
> craftbukkit.jar
3
>
>
>
> Bei "dir" →
>>     proc.StartInfo.WorkingDirectory = "dir";
>  muss ich quasi das Verzeichnis eintragen, wo die craftbukkit.jar ist,
> da diese im Server Hauptverzeichnis liegt, wo alle Plugins/wichtige
> Daten sind.
>
> Nur bei dieser Zeile bin ich mir jetzt nich ganz sicher:
>>     proc.StartInfo.EnvironmentVariables.Add("BINDIR", "dir");
> was muss ich bei "BINDIR" eintragen, und muss in "dir" das gleiche wie
> in
>>     proc.StartInfo.WorkingDirectory = "dir";

@ECHO OFF
SET BINDIR=%~dp0
CD /D "%BINDIR%"
"%ProgramFiles(x86)%\Java\jre6\bin\java.exe" -Xms1024M -Xmx1024M -jar 
craftbukkit.jar
list
PAUSE

Die Batch-Datei holt sich mit %~dp0 das erste Argument (Laufwerk+Pfad) 
was der Batch-Datei übergeben wurde (was nichts anderes als das 
Verzeichnis ist, in der sie liegt).
-> BINDIR und WorkingDirectory = dir = Verzeichnis der Batch-Datei

von Pascal H. (pase-h)


Lesenswert?

Ok.
ich hab jetzt folgendes eingetragen:
1
 proc.StartInfo.FileName = @"J:\Program Files (x86)\Java\jre6\bin\java.exe";
2
 proc.StartInfo.WorkingDirectory = @"J:\Users\Pascal\Desktop\Minecraft 
3
roc.StartInfo.EnvironmentVariables.Add(@"J:\Users\Pascal\Desktop\Minecraft Server", @"J:\Users\Pascal\Desktop\Minecraft Server");
4
    proc.StartInfo.Arguments = " -Xms1024M -Xmx1024M -jar craftbukkit.jar";Server";

wenn ich jetzt denn Button betätige, dann Reagiert das Programm nicht 
mehr (z.B. kann ich das Programm nicht mehr verschieben oder kann keine 
Buttons mehr drücken u.v.m), und ich habe ca. 50% bis 60% CPU 
Auslastung.

Das Programm kann ich nur noch über Visual c# mit "Debugging beenden" 
beenden.

Achja, die Craftbukkit.jar liegt im gleichen Verzeichnis wie die 
Start.bat

Aber was ist falsch an dem Code?

Mfg
pase-h

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Pascal H. schrieb:
> Aber was ist falsch an dem Code?

Ich vermute mal ganz stark, das es kein Toller Plan ist im 
ButtonHnadler den Prozess zu starten und dort auf dessen Beendigung zu 
warten.

Wie oben beschrieben sollte man so etwas in einen separaten Thread 
auslagern.

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
Noch kein Account? Hier anmelden.