c# Externes Programm und Ausgabe auswerten

Tobi81

Mitglied
Hallo Forum,

ich möchte in meiner Anwendung ein externes DOS-Programm starten (am liebsten unsichtbar wenn das geht), solange warten bis das Programm beendet ist (kann auch mal Stunden dauert), und die Ausgabe die das externe Programm generiert hat, auswerten.

Kann mir jemand sagen wie sowas geht?

Vielen Dank,
Tobias
 
Danke Alex, dass du dir trotz der 'schon oft gefragten Frage' dir die Mühe gemacht hast mir den Link zu nennen.

Daraufhin habe ich folgendes zusammengebastelt:
Code:
Process compiler = new Process();
compiler.StartInfo.FileName = "C:\\ldsgen.exe";
compiler.StartInfo.Arguments = parameters;
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
compiler.Start();
string ldsoutput = compiler.StandardOutput.ReadToEnd();
compiler.WaitForExit();
Das funktioniert auch alles soweit richtig gut (auf Ergebnis der Konsole warten und den Output in einem String speichern), jedoch reagiert meine c# Windows-Anwendung währenddessen nicht.
Mein Problem ist, dass die Ausführung des Konsolen-Programms schon ne Stunde dauern kann, und da wäre es schon schön wenn die Anwendung weiterhin nutzbar ist. Am "compiler.WaitForExit()" liegt es nicht, das habe ich schon rausgenommen.

Geht das irgendwie?
Vermutlich muss ich das ganze in einen Thread packen? Hat da jemand ein gutes Beispiel?


Vielen Dank,
Tobias
 
Dein Programm tut nichts anderes, während es auf die Ausgabe vom Konsolenprogramm wartet, solange alles in einem Thread läuft.
Du kannst jedoch einen zweiten Thread erstellen (Thread bedeuted Faden, also stell es dir vor, dass das Programm an einem 2. Faden weiter abläuft), der das Konsolenprogramm startet und auf die Rückgabe wartet, während dein Hauptprogramm weiterhin normal laufen kann und auf Benutzereingaben, z.B. das Drücken eines Buttons warten kann.

Diesen 2. Thread kannst du entweder manuell erstellen, hier ein ganz gutes Tutorial, oder du kannst die BackgroundWorker-Klasse vom .NET Framework verwenden.

Ich hoffe, damit habe ich dir geholfen!
 
Hallo multimolti,

vielen Dank für deine Antwort erstmal!
Ich bin jetzt wieder mit der Antwort von Alex am kämpfen da ich es mit den Threads auch nicht so richtig hinbekommen habe... :(

Mein aktueller Code mit dem OutputDataReceived-Event sieht momentan so aus:
Code:
Process compiler;
compiler = new Process();
compiler.StartInfo.FileName = "C:\\ldsgen.exe";
compiler.StartInfo.Arguments = "";
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
sortOutput = new StringBuilder(""); 
compiler.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler); 
compiler.StartInfo.RedirectStandardInput = true; 
compiler.Start();
StreamWriter sortStreamWriter = compiler.StandardInput; 
compiler.BeginOutputReadLine();
sortStreamWriter.Close(); 
compiler.WaitForExit();
compiler.Close();

Also praktisch genau wie in dem Beispiel.
Nur leider ist die Anwendung die die Shell-Anwendung startet genauso blockiert wie vorher auch. Irgendwas scheint da nicht zu stimmen.

Hat jemand eine Ahnung was da nicht stimmt?


Danke,
Tobias
 
Hallo multimolti,

ich habe mir aus dem zweiten Thread-Beispiel folgenden Code zusammengbaut:

Code:
public static DataGridViewRow row;    // damit row im Thread verfügbar ist
public static Object lockvar = ""; 

// Funktion die den Thread erstellt
private void btlds_Click(object sender, EventArgs e)
{
    foreach (DataGridViewRow row in dataGridLds.Rows)
    {
        Thread[] ta = new Thread[1]; // Thread-Array
        ta[0] = new Thread(new ThreadStart(tuwas)); // Threads werden erzeugt
        ta[0].Start(); // Threads werden gestartet
    }

}

public static void tuwas()
{
    lock (lockvar)
    {
        
        string tblcode = Convert.ToString(row.Cells[1].Value);
        
        Process compiler;
        compiler = new Process();
        compiler.StartInfo.FileName = "C:\\ldsgen.exe";
        compiler.StartInfo.Arguments = tblcode;
        compiler.StartInfo.UseShellExecute = false;
        compiler.StartInfo.RedirectStandardOutput = true;
        sortOutput = new StringBuilder(""); 
        compiler.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler); 
        compiler.StartInfo.RedirectStandardInput = true; 
        compiler.Start();
        StreamWriter sortStreamWriter = compiler.StandardInput; 
        string ldsoutput = compiler.StandardOutput.ReadToEnd();
        sortStreamWriter.Close(); 
        compiler.WaitForExit();
        compiler.Close(); 
        
    }
}

Problematisch (für mich) ist, dass ich einen DataGrid benutzte in denen Daten vom Thread ausgelesen und wieder gespeichert werden.
Das bekomme ich nicht ganz hin:

Das Problem kommt in der tuwas() Methode in der ersten Zeile:
string tblcode = Convert.ToString(row.Cells[1].Value);
>> Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

Am Ende des Threads will ich auch noch was in den DataGrid schreiben.

Und wie kann ich erreichen, dass immer nur ein Thread parallel zum Hauptprogramm läuft?


Vielen Dank,
Tobias
 
Wenn mir jemand sagen könnte, wie ich aus dem Thread auf das row-Objekt zugreifen kann, wär das echt super und ich wär totaaaal Glücklich! :)
 
Ich habs geschafft! Die Lösung zu posten wär allerdings quatsch, da sie so trivial ist, das es mir schon fast peinlich ist. Ist absolutes Grundwissen.

Da dies aber mein erstes c# Programm ist, hab ich das nicht gleich gemerkt.

Vielen Dank an Alex und multimolti für ihre Hilfe :)
 

Neue Beiträge

Zurück