myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Grundlagen von C# » RedirectStandardOutput DosShell unter W7 und neuer
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

RedirectStandardOutput DosShell unter W7 und neuer

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Zerstreute
myCSharp.de-Mitglied

Dabei seit: 04.05.2017
Beiträge: 4
Entwicklungsumgebung: Visual Studio Com. 2015
Herkunft: NRW


Zerstreute ist offline

RedirectStandardOutput DosShell unter W7 und neuer

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Zusammen,

ich habe mich mal wieder festgefressen bei einem Problem das wahrscheinlich viel einfacher zu lösen ist als ich denke.

Folgendes habe ich vor :

Ich schreibe an einer GUI für einen Ton-Generator der als Commandozeilentool vorliegt.
Dieser Generator wird mit Angabe von SampleFrequenz und Sinusfrequenz und weiteren Parametern gestartet, läuft dann im Fenster so lange bis man eine Taste drückt. In dieser Zeit läuft in diesem Fenster noch ein Zähler wodurch der Datenstrom in dem Fenster nicht aufhört bis man das Programm beendet oder im Fenster die Space Taste drückt.

Eine Teilfunktion meines Tools soll sein die möglichen Samplefrequenzen der ausgewählten Soundkarte zu erkennen.

Dazu starte ich das Tool einmal mit jeder bekannten Samplefrequenz und möchte eigentlich gern das er soweit kein Fehler auftritt sofort das Programm beendet und mit der nächsten Frequenz weiter macht. Leider wird die von mir vorgesehene Umleitung des Output Stroms nicht wie gewünscht angesprungen wodurch das Programm in eine Endlosschleife gerät und nicht weiter arbeitet bis ich das externe Fenster schließe.

Hier ist mein bisheriger Lösungansatz, der leider nicht wie gewünscht funktioniert :

C#-Code:
...
Process Gen = new Process();
...
                        void Button_testClick(object sender, EventArgs e)
        {

            Gen.StartInfo.UseShellExecute=false;
            Gen.StartInfo.RedirectStandardOutput=true;
            Gen.OutputDataReceived +=proc_OutputDataReceived;
            Gen.StartInfo.RedirectStandardError=true;
            Gen.StartInfo.CreateNoWindow=false;

            for (int i=0;i<comboBox_SampleFreq.Items.Count;i++)
            {

                comboBox_SampleFreq.SelectedIndex=i;
                KillTasks();
                Gen.StartInfo.Arguments=Param.AsioArguments;

                Gen.Start();
                Gen.BeginOutputReadLine();
                if (Gen.StandardError.Peek()>0)
                {
                    comboBox_SampleFreq.Items.RemoveAt(i--);

                }

            }
            Gen.OutputDataReceived -=proc_OutputDataReceived;
            comboBox_SampleFreq.SelectedIndex=0;
        }
        void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
                string text =  e.Data;
                KillTasks();
        }
        void KillTasks()
        {
            foreach (Process p in Process.GetProcessesByName(AsioTool.Replace(".exe",""))) {
                p.Kill();
                Thread.Sleep(500);
            }
        }

Hängt das Tool weil ich den Datenstrom im selben Thread laufen lasse wie die Hauptanwendung ? Oder wo liegt hier das Problem das nach ausführung von Gen.Start() alles wartet ?

Würde mich hier über Kritik, Anregungen und Hilfe sehr freuen.

Danke schonmal im Vorraus
04.04.2019 16:31 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
trashkid2000 trashkid2000 ist männlich
myCSharp.de-Mitglied

Dabei seit: 27.12.2010
Beiträge: 155


trashkid2000 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

also sowas ist böse:

C#-Code:
comboBox_SampleFreq.SelectedIndex=i;

Was der User ausgewählt hat, solltest Du so belassen. Das gibt sonst nur Probleme.
Und wozu das?

Viel schlimmer ist aber noch das:

C#-Code:
if (Gen.StandardError.Peek()>0)
{
   comboBox_SampleFreq.Items.RemoveAt(i--);
}

Was kann die "arme ComboBox" dafür, dass Fehler auftreten? Die Items sollten hier ziemlich konstant sein!
05.04.2019 23:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
trashkid2000 trashkid2000 ist männlich
myCSharp.de-Mitglied

Dabei seit: 27.12.2010
Beiträge: 155


trashkid2000 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich sehe da eindeutig zu viele

C#-Code:
KillTasks();
05.04.2019 23:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.359
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist offline Füge T-Virus Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Un das Thread.Sleep(500); sieht auch noch sehr falsch aus.
Dadurch blockierst du deine UI bei jedem Aufruf aktuell 500ms lang.
Das dürfte den Nutzer auch nicht freuen, wenn das Programm immer wieder ohne Erklärung für ihn hängt.

T-Virus
06.04.2019 09:53 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zerstreute
myCSharp.de-Mitglied

Dabei seit: 04.05.2017
Beiträge: 4
Entwicklungsumgebung: Visual Studio Com. 2015
Herkunft: NRW

Themenstarter Thema begonnen von Zerstreute

Zerstreute ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von trashkid2000:
Ich sehe da eindeutig zu viele

C#-Code:
KillTasks();

tja .. leider ist die einzige Alternative die kontrolle über das DOS Tool zu nehmen und über windows an das Fenster den Druck der Space Taste zu simulieren - was am Ende übrigens nix anderes macht als das Programm zu beenden..

Vom Ablauf her sieht das so aus :

Programm mit Parametern starten .. dieses läuft dann im Shell Fenster und wartet auf "Space"-Druck in dieser Zeit zählt einfach nur ein Zähler die bereits abgespielten Samples.

Über 'Kill Prozess' stelle ich nur sicher das definitiv immer nur eine Instanz des Programms läuft da 2 Instanzen nicht gleichzeitig auf die ASIO Schnittstelle zugreifen können.

Was das Anpassen der KomboBox betrifft, hier wird diese Schleife vor der Freigabe der Box für den Benutzer modifiziert. Im Idealfall würde die Prüfung und Anpassung innerhalb weniger Millisekunden abgeschlossen sein. Der Grund für dieses unschöne Vorgehen ist, das ich über das externe Tool die "angeblich möglichen Samplefrequenzen" abfragen kann aber es mir leider immer alle von sich selbst unterstützten, jedoch nicht nur die von der Hardware unterstützen Frequenzen angibt. Daher muß ich, um es für den Benutzer möglichst ohne Fehlermeldungen laufen zu lassen, die Combobox immer beim Wechsel des ASIO Devices neu befüllen und dabei die nicht unterstützten entfernen.

Was ich mir jedoch als alternative Lösung vorstellen könnte, wäre:
Ich prüfe nur die kritischen Frequenzen und befülle dann die ComboBox mit den übrigen Frequenzen. Das wäre sicherlich auch vom Code her deutlich schöner und käme auch mit weniger Kills aus.

Abschließend nur ein Hinweis auf die Sleeps. Diese habe ich hinzugefügt weil es ohne Wartezeit z.T. Probleme beim Start des Shell Programms gab. Hier könnte ich sicherlich auch die Wartezeit noch etwas reduzieren.

Am Ende habe ich jetzt aber irgendwie den Eindruck das keiner von Euch mir sagen kann warum mein Programm hängt sobald das externe Tool gestartet wurde (und ohne Fehler läuft).
11.04.2019 15:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.359
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist offline Füge T-Virus Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Um nur eine Instanz deines Programms zu erlauben, solltest du ein Mutex verwenden.
Damit setzt du Systemweit ein Lock in einem Programm, musst du dann nur beim beenden wieder freigeben.
Alternativ zum Mutex kannst du dir auch über die Process Klasse alle laufenden Prozesse holen und schauen ob deiner gerade ausgeführt wird mit einer anderen Process ID als deiner aktuellen.
Damit sparst du dir das KillTasks eigentlich komplett weg.

Dein Programm wird entweder in deinem KillTasks oder an einer anderen Stelle hängen.
Dies kannst du per Debugger prüfen, ansonsten solltest du dir auch ein Log schreiben um deinem Problem auf die Schliche zu kommen.

T-Virus
11.04.2019 19:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MarsStein MarsStein ist männlich
myCSharp.de-Poweruser/ Experte

avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 3.130
Entwicklungsumgebung: VS 2013, MonoDevelop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

Zitat von Zerstreute:
das keiner von Euch mir sagen kann warum mein Programm hängt sobald das externe Tool gestartet wurde

Eine Vermutung hätte ich schon anzubieten: das OutputDataReceived-Event wird nur ausgelöst, wenn das externe Programm eine vollständige Zeile inklusive Zeilenumbruch schreibt.
Vermutlich ist das nicht der Fall, dann müsstest Du selbst direkt auf dem StandardOutput-Stream lesen.

Gruß, MarsStein
12.04.2019 10:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zerstreute
myCSharp.de-Mitglied

Dabei seit: 04.05.2017
Beiträge: 4
Entwicklungsumgebung: Visual Studio Com. 2015
Herkunft: NRW

Themenstarter Thema begonnen von Zerstreute

Zerstreute ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von MarsStein:
Eine Vermutung hätte ich schon anzubieten: das OutputDataReceived-Event wird nur ausgelöst, wenn das externe Programm eine vollständige Zeile inklusive Zeilenumbruch schreibt.

Hallo MarsStein,

so was in der Art ist auch meine Vermutung da sobald ich das externe Programm starte auch mein Programm im Debugger keine Zeile weiter abarbeitet. Sprich sobald ich im Einzelschritt Betrieb den Process.Start() ausgeführt hab, gehts einfach im Programm nirgends weiter und eine Fehlermeldung bekomme ich auch nicht.

Obwohl im Fenster (bei nicht umgeleitetem Output) mehrere Zeilen stehen, scheint der StreamReader nicht ausgelöst zu werden. Ich befürchte beinahe das im externen Programm noch ein Programm oder Prozess gestartet wird der nicht im Output Stream ausgegeben wird. (ähnlich wie bei Putty)

könnte ich sowas irgendwie heraus bekommen ?

Gruß und Dank schonmal an alle
16.04.2019 09:18 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 7 Monate.
Der letzte Beitrag ist älter als 7 Monate.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 23.11.2019 02:23