[c#] Gewusst wie: Ausführen der Befehlszeile in C #, erhalten Sie STD OUT-Ergebnisse


Answers

Hier ist ein kurzes Beispiel:

//Create process
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();

//strCommand is path and file name of command to run
pProcess.StartInfo.FileName = strCommand;

//strCommandParameters are parameters to pass to program
pProcess.StartInfo.Arguments = strCommandParameters;

pProcess.StartInfo.UseShellExecute = false;

//Set output of program to be written to process output stream
pProcess.StartInfo.RedirectStandardOutput = true;   

//Optional
pProcess.StartInfo.WorkingDirectory = strWorkingDirectory;

//Start the process
pProcess.Start();

//Get program output
string strOutput = pProcess.StandardOutput.ReadToEnd();

//Wait for process to finish
pProcess.WaitForExit();
Question

Wie führe ich ein Befehlszeilenprogramm von C # aus und bekomme die STD OUT-Ergebnisse zurück. Insbesondere möchte ich DIFF für zwei programmgesteuert ausgewählte Dateien ausführen und die Ergebnisse in ein Textfeld schreiben. Ja, ich könnte das selbst herausfinden, aber sicherlich hat jemand anderes so etwas gemacht und ich bin faul ...




Die akzeptierte Antwort auf dieser Seite hat eine Schwäche, die in seltenen Situationen unangenehm ist. Es gibt zwei Dateizugriffsnummern, in die Programme per Konvention, stdout und stderr schreiben. Wenn Sie nur ein einzelnes Datei-Handle wie die Antwort von Ray lesen, und das Programm, das Sie starten, schreibt genug Ausgabe an stderr, wird es den Ausgabe-stderr-Puffer und -Block füllen. Dann sind Ihre beiden Prozesse festgefahren. Die Puffergröße kann 4K sein. Dies ist extrem selten bei kurzlebigen Programmen, aber wenn Sie ein lang laufendes Programm haben, das wiederholt zu stderr ausgibt, wird es schließlich geschehen. Dies ist schwierig zu debuggen und aufzuspüren.

Es gibt ein paar gute Möglichkeiten, damit umzugehen.

  1. Eine Möglichkeit besteht darin, cmd.exe anstelle von Ihrem Programm auszuführen und das Argument / c zu cmd.exe zu verwenden, um Ihr Programm zusammen mit dem Argument "2> & 1" zu cmd.exe aufzurufen, um es dazu zu bringen, stdout und stderr zusammenzuführen.

            var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
    
  2. Eine andere Möglichkeit besteht darin, ein Programmiermodell zu verwenden, das beide Handles gleichzeitig liest.

            var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = @"/c dir \windows";
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardInput = false;
            p.OutputDataReceived += (a, b) => Console.WriteLine(b.Data);
            p.ErrorDataReceived += (a, b) => Console.WriteLine(b.Data);
            p.Start();
            p.BeginErrorReadLine();
            p.BeginOutputReadLine();
            p.WaitForExit();
    



// usage
const string ToolFileName = "example.exe";
string output = RunExternalExe(ToolFileName);

public string RunExternalExe(string filename, string arguments = null)
{
    var process = new Process();

    process.StartInfo.FileName = filename;
    if (!string.IsNullOrEmpty(arguments))
    {
        process.StartInfo.Arguments = arguments;
    }

    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.StartInfo.UseShellExecute = false;

    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardOutput = true;
    var stdOutput = new StringBuilder();
    process.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data); // Use AppendLine rather than Append since args.Data is one line of output, not including the newline character.

    string stdError = null;
    try
    {
        process.Start();
        process.BeginOutputReadLine();
        stdError = process.StandardError.ReadToEnd();
        process.WaitForExit();
    }
    catch (Exception e)
    {
        throw new Exception("OS error while executing " + Format(filename, arguments)+ ": " + e.Message, e);
    }

    if (process.ExitCode == 0)
    {
        return stdOutput.ToString();
    }
    else
    {
        var message = new StringBuilder();

        if (!string.IsNullOrEmpty(stdError))
        {
            message.AppendLine(stdError);
        }

        if (stdOutput.Length != 0)
        {
            message.AppendLine("Std output:");
            message.AppendLine(stdOutput.ToString());
        }

        throw new Exception(Format(filename, arguments) + " finished with exit code = " + process.ExitCode + ": " + message);
    }
}

private string Format(string filename, string arguments)
{
    return "'" + filename + 
        ((string.IsNullOrEmpty(arguments)) ? string.Empty : " " + arguments) +
        "'";
}



Es gibt eine ProcessHelper-Klasse in PublicDomain Quellcode, die Sie interessieren könnte.




Sie müssen ProcessStartInfo mit aktiviertem RedirectStandardOutput - dann können Sie den Ausgabestream lesen. Sie können es einfacher finden, ">" zu verwenden, um die Ausgabe in eine Datei umzuleiten (über das Betriebssystem), und dann einfach die Datei zu lesen.

[Bearbeiten: wie Ray es getan hat: +1]




Sie können ein beliebiges Befehlszeilenprogramm mit der Process-Klasse starten und die StandardOutput-Eigenschaft der Process-Instanz mit einem von Ihnen erstellten Stream-Reader festlegen (entweder basierend auf einer Zeichenfolge oder einem Speicherort). Nachdem der Vorgang abgeschlossen ist, können Sie dann den gewünschten Unterschied für diesen Stream festlegen.




Related