none
Konsolenprogramme mit GUI? RRS feed

  • Frage

  • Hallo liebes Forum,

    ich bin ziemlich neu in der C#-Welt habe aber gute Kenntnisse in Java :)
    Mein Vorhaben ist es eine Oberfläche für ein Konsolenprogramm zu basteln.

    Dazu erstelle ich einen Prozess mit der Anwendung, starte sie, führe die Operationen aus und lese dann den Output aus.
    Das Problem hierbei ist, sobald ich den Prozess starte, öffnet sich ein Konsolenfenster und wartet solange mit dem Output, bis ich das Fenster schließe. Den Output speichere ich in einem String, und dieser wird eben erst dann beschrieben, wenn ich das Fenster selbst schließe. Ansonsten geht das Programm einfach nicht weiter. Starte ich das Programm OHNE Fenster und verstecke es einfach, ja dann kann ich halt gar nichts machen und das Programm wartet alleine vor sich hin.

    Meine Frage nun: Wie kann ich die Operationen komplett durchlaufen lassen, ohne dass die Eingabeaufforderungen auf das Schließen des Fensters wartet (Warum das überhaupt so ist, verstehe ich auch nicht).

    Vielen Dank im Voraus :)

    public void ExecuteCMDCommand(string command)
            {
                System.Diagnostics.Process process = new System.Diagnostics.Process();
                process.StartInfo.FileName = @"C:\Windows\PfadZumProgramm";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.CreateNoWindow = false;
    
                //process.StartInfo.WorkingDirectory = "C:\\Windows\\System32\\";
                process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
                process.EnableRaisingEvents = true;
    
                process.Start();
    
                //input
                process.StandardInput.WriteLine("Input für die Konsole");
    
    // AN DIESER STELLE GEHT ES NICHT WEITER, SOLANGE DAS FENSTER GEÖFFNET IST
                string output = process.StandardOutput.ReadToEnd(); 
                process.WaitForExit();
                richTextBox1.Text = output;
    }

    Mittwoch, 4. November 2015 18:26

Antworten

  • Hallo,

    wenn der Prozess bereits beendet ist, dann ist das Fenster auch zu. CloseMainWindow funktioniert nur wenn der Prozess noch läuft und die Anwendung auch ein eigenes Fenster hat. Ansonsten wäre der Aufruf von Kill eine Möglichkeit, aber auch hier muss der Prozess noch laufen.

    Ich nehme an die empfohlene Anpassung beim Input hast Du bereits vorgenommen?

    //input
    process.StandardInput.WriteLine("Input für die Konsole");
    process.StandardInput.Close();

    Möglicherweise bietet das Konsolenprogramm eine Möglichkeit zur externen Steuerung, z. B. via Kommandozeilenparameter oder über eine Schnittstelle.

    Gruß


    - Florian

    Freitag, 6. November 2015 08:12

Alle Antworten

  • Hallo,

    ein fremdes Programm zu kontrollieren ist nur selten wirklich möglich. Das liegt einfach daran dass der Entwickler des anderen Programms etwas programmiert hat worauf kein anderer Zugriff hat.

    Das von dir beschriebene Problem kann viele Ursachen haben, siehe hier. Ich rate dir dazu mal die Flush- und auch die Close-Methode auf den StandardInput-Stream anzuwenden bevor du ReadToEnd aufrufst.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Mittwoch, 4. November 2015 19:44
    Moderator
  • Leider immer noch das gleiche Problem, es öffnet sich ein leeres CMD-Fenster, welches ich immer schließen muss, damit es weitergeht.

    Kann ich denn nicht irgendwie direkt auf das sich öffnende Fenster zugreifen, damit ich es schließen kann?
    Es muss doch irgendwo auch instanziiert werden, oder habe ich da keinen Zugriff darauf?

    Mittwoch, 4. November 2015 20:26
  • Hallo Mr. Saltberg,

    Du weist in deinem Code an auf das Ende des Prozesses zu warten, daher kann dort auch nichts weiterlaufen bevor dieser beendet wird.

    process.WaitForExit(); //MSDN: "Weist die Process-Komponente an, unbestimmte Zeit zu warten, bis der zugeordnete Prozess beendet wird.";
    
    richTextBox1.Text = output;
    Zum Schließen des Fensters kann man CloseMainWindow() aufrufen.
    process.CloseMainWindow();

    Du könntest also die Reihenfolge in deinem Code entsprechend anpassen:

    string output = process.StandardOutput.ReadToEnd();
    richTextBox1.Text = output;
    process.CloseMainWindow();
    process.WaitForExit();
    Gruß


    - Florian


    • Bearbeitet Florian Haupt Donnerstag, 5. November 2015 10:28 Darstellungsfehler
    Donnerstag, 5. November 2015 10:26
  • 
    


    string output = process.StandardOutput.ReadToEnd();
    richTextBox1.Text = output;
    process.CloseMainWindow();
    process.WaitForExit(); Gruß


    - Florian

    Hi Florian,

    die von dir beschriebene Lösung klappt leider auch nicht.
    Die CloseMainWindow() Methode kenne ich sogar und habe sie schon ausprobiert, hat leider nicht geholfen. Zumal ich sogar die WaitForExit() Methode komplett herausnehmen kann und es ändert sich trotzdem nichts an der Tatsache, dass sich das Fenster öffnet.

    Wenn ich jedoch den von dir beschriebenen Code übernehme, bekomme ich nach Schließen des CMD-Fensters eine InvalidOperationException genau an der Stelle, wo CloseMainWindow() aufgerufen wird, da ja der Prozess an der Stelle bereits beendet ist (Ich scheine ihn ja immer durch das Schließen des Fensters zu beenden).

    Ich kriege es jedoch nicht hin, dass sich der Prozess ohne mein Zutun beendet.


    Edit: Wie auch bereits gesagt, hängt der Prozess definitiv an der ReadToEnd() Methode beim StandardOutput, laut Debugger. Also wenn sich das Fenster öffnet, ist das Programm im Code genau an der ReadToEnd() Methode und führt das Programm nur weiter fort, wenn das sich öffnende Fenster schließe.
    • Bearbeitet Mr. Saltberg Donnerstag, 5. November 2015 19:34
    Donnerstag, 5. November 2015 19:32
  • Hallo,

    ein Konsolenprogramm hat kein Fenster wie man es vielleicht erwarten würde. Man kann zwar an ein Handle kommen um das Fenster zu kontrollieren, würde hier meiner Meinung nach aber auch nicht viel bringen.

    Im Notfall kannst du den Process über das ebendiese Objekt per Kill-Methode abschießen. Das ist dann wie wenn man einen Prozess über den Taskmanager beendet.

    Aber wie schon mal angemerkt, kannst du dir nie sicher sein dass der Prozess fertig ist.

    Wenn du die Anwendung normal aufrufst (über den Explorer), bleibt das Fenster dann auch offen?


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 5. November 2015 19:50
    Moderator
  • Ja tut es
    Donnerstag, 5. November 2015 20:03
  • Ok, und ich vermute mal das es sich schließt sobald du eine Taste drückst, richtig? So ist es zumindest bei vielen Konsolenprogrammen. Ich diesem Fall würde ich versuchen eine Taste an das Fenster zu senden (Stichwort: SendKeys oder aber die WinAPI bietet nochmal etwas eigenes dafür). Das wäre bedingt schöner als das Beenden des Prozesses. Das Problem hierbei ist noch dass du das in den Vordergrund holen des Fensters und das Senden einer Taste solange wiederholen musst, bis das Fenster zu ist. Das sollte daher in einem 2. Thread geschehen. Ob das Fenster noch offen ist (bzw. ob der Prozess noch existiert) müsstest du über das Process-Objekt herausfinden können.

    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 5. November 2015 20:56
    Moderator
  • Hallo,

    falls du einen Java-Prozess starten willst, hilft dir vielleicht der Hinweis auf Jline weiter.

    Ansonsten helfen vielleicht die Hinweise in diesem Thread mit Event-Handlern.

    Gruß Heiko


    Donnerstag, 5. November 2015 23:13
  • Hallo,

    wenn der Prozess bereits beendet ist, dann ist das Fenster auch zu. CloseMainWindow funktioniert nur wenn der Prozess noch läuft und die Anwendung auch ein eigenes Fenster hat. Ansonsten wäre der Aufruf von Kill eine Möglichkeit, aber auch hier muss der Prozess noch laufen.

    Ich nehme an die empfohlene Anpassung beim Input hast Du bereits vorgenommen?

    //input
    process.StandardInput.WriteLine("Input für die Konsole");
    process.StandardInput.Close();

    Möglicherweise bietet das Konsolenprogramm eine Möglichkeit zur externen Steuerung, z. B. via Kommandozeilenparameter oder über eine Schnittstelle.

    Gruß


    - Florian

    Freitag, 6. November 2015 08:12
  • So, etwas verspätet: Das hat's gebracht!

    Wenn ich den StandardInput nach Nutzung schließe, dann klappt es.
    Der Prozess schließt sich von selbst, sogar mit verstecktem Fenster!

    Danke an dieser Stelle :)

    edit: Vielleicht noch eine Idee, weshalb die Umlaute nicht richtig angezeigt werden? Ich kriege letztlich nur einen String zurück als Output...

    edit2: Es scheint wohl an dem EncodingTyp zu liegen, allerdings kann ich keinen StreamReader anlegen, der aus dem Prozess ausliest, denn ich kann doch nur bei der Initialisierung des StreamReaders den EncodingTyp festlegen, oder kann ich den nachträglich im Standardoutput festlegen?


    edit3:
    process.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF7;
    UTF8 und 32 und ASCII etc. alles ausprobiert, aber ich kriege nichts mit Umlauten, wie kann das sein :D
    Sonntag, 15. November 2015 16:53