Ich möchte ein externes Befehlszeilenprogramm von meiner Mono/.NET-App aus ausführen. Zum Beispiel möchte ich mencoder ausführen. Ist es möglich:
Wenn Sie Ihre Process
-Objektgruppe StartInfo
entsprechend erstellen:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "program.exe",
Arguments = "command line arguments to your executable",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
starten Sie dann den Prozess und lesen Sie daraus:
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
// do something with line
}
Sie können int.Parse()
oder int.TryParse()
verwenden, um die Zeichenfolgen in numerische Werte umzuwandeln. Möglicherweise müssen Sie zuerst einige Zeichenfolgen bearbeiten, wenn die gelesenen Zeichenfolgen ungültige numerische Zeichen enthalten.
Sie können Ihre Ausgabe synchron oder asynchron verarbeiten.
1: Synchrones Beispiel
static void runCommand()
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR"; // Note the /c command (*)
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
//* Read the output (or the error)
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
string err = process.StandardError.ReadToEnd();
Console.WriteLine(err);
process.WaitForExit();
}
Hinweis, dass es besser ist, sowohl output als auch error zu verarbeiten: Sie müssen separat behandelt werden.
(*) Für einige Befehle (hier StartInfo.Arguments
) müssen Sie den /c
Direktive hinzufügen, ansonsten friert der Prozess in der WaitForExit()
.
2: Asynchrones Beispiel
static void runCommand()
{
//* Create your Process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
//* Start process and handlers
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}
Wenn Sie keine komplizierten Operationen mit der Ausgabe durchführen müssen, können Sie die OutputHandler-Methode umgehen, indem Sie die Handler direkt inline hinzufügen:
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
In Ordnung, für alle, die sowohl Fehler als auch Ausgaben lesen möchten, aber Deadlocks mit einer der Lösungen erhalten, die in anderen Antworten (wie mir) angegeben sind, hier eine Lösung, die ich nach dem Lesen der MSDN-Erklärung für die StandardOutput-Eigenschaft erstellt habe.
Die Antwort basiert auf dem Code von T30:
static void runCommand()
{
//* Create your Process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//* Set ONLY ONE handler here.
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
//* Start process
process.Start();
//* Read one element asynchronously
process.BeginErrorReadLine();
//* Read the other one synchronously
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}
Die Standardmethode von .NET ist das Lesen aus dem Process ' StandardOutput - Stream. In den verknüpften MSDN-Dokumenten finden Sie ein Beispiel. Ähnlich können Sie von StandardError lesen und in StandardInput schreiben.
sie können den gemeinsam genutzten Speicher für die beiden Prozesse verwenden, um durch zu kommunizieren, auschecken MemoryMappedFile
sie erstellen hauptsächlich eine mit dem Speicher verknüpfte Datei mmf
im übergeordneten Prozess mithilfe der "using" -Anweisung. Dann erstellen Sie den zweiten Prozess bis zum Abschluss und lassen das Ergebnis mit mmf
in die BinaryWriter
schreiben Lesen Sie dann das Ergebnis von mmf
mit dem übergeordneten Prozess. Sie können den Namen mmf
auch mit Befehlszeilenargumenten oder mit einem harten Code übergeben.
vergewissern Sie sich bei der Verwendung der zugeordneten Datei im übergeordneten Prozess, dass der untergeordnete Prozess das Ergebnis in die zugeordnete Datei schreibt, bevor die zugeordnete Datei im übergeordneten Prozess freigegeben wird
Beispiel: Übergeordneter Prozess
private static void Main(string[] args)
{
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("memfile", 128))
{
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(512);
}
Console.WriteLine("Starting the child process");
// Command line args are separated by a space
Process p = Process.Start("ChildProcess.exe", "memfile");
Console.WriteLine("Waiting child to die");
p.WaitForExit();
Console.WriteLine("Child died");
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader reader = new BinaryReader(stream);
Console.WriteLine("Result:" + reader.ReadInt32());
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
Kindprozess
private static void Main(string[] args)
{
Console.WriteLine("Child process started");
string mmfName = args[0];
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(mmfName))
{
int readValue;
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader reader = new BinaryReader(stream);
Console.WriteLine("child reading: " + (readValue = reader.ReadInt32()));
}
using (MemoryMappedViewStream input = mmf.CreateViewStream())
{
BinaryWriter writer = new BinaryWriter(input);
writer.Write(readValue * 2);
}
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
um dieses Beispiel verwenden zu können, müssen Sie eine Lösung mit zwei Projekten erstellen. Dann nehmen Sie das Build-Ergebnis des untergeordneten Prozesses aus% childDir%/bin/debug und kopieren es in% parentDirectory%/bin/debug übergeordnetes Projekt
childDir
und parentDirectory
sind die Ordnernamen Ihrer Projekte auf dem PC Viel Glück :)
Die Befehlszeilen-Shell-Ausgabe eines Prozesses kann wie folgt abgerufen werden: http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx
Dies hängt vom Mencoder ab. Wenn dieser Status in der Befehlszeile ausgegeben wird, dann ja :)
So starten Sie einen Prozess (z. B. eine bat-Datei, ein Perl-Skript, ein Konsolenprogramm) und lassen dessen Standardausgabe in einem Windows-Formular anzeigen
processCaller = new ProcessCaller(this);
//processCaller.FileName = @"..\..\hello.bat";
processCaller.FileName = @"commandline.exe";
processCaller.Arguments = "";
processCaller.StdErrReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.StdOutReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.Completed += new EventHandler(processCompletedOrCanceled);
processCaller.Cancelled += new EventHandler(processCompletedOrCanceled);
// processCaller.Failed += no event handler for this one, yet.
this.richTextBox1.Text = "Started function. Please stand by.." + Environment.NewLine;
// the following function starts a process and returns immediately,
// thus allowing the form to stay responsive.
processCaller.Start();
Sie finden ProcessCaller
unter diesem Link: Prozess starten und Standardausgabe anzeigen
Sie können die Prozessausgabe mit dem folgenden Code protokollieren:
ProcessStartInfo pinfo = new ProcessStartInfo(item);
pinfo.CreateNoWindow = false;
pinfo.UseShellExecute = true;
pinfo.RedirectStandardOutput = true;
pinfo.RedirectStandardInput = true;
pinfo.RedirectStandardError = true;
pinfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
var p = Process.Start(pinfo);
p.WaitForExit();
Process process = Process.Start(new ProcessStartInfo((item + '>' + item + ".txt"))
{
UseShellExecute = false,
RedirectStandardOutput = true
});
process.WaitForExit();
string output = process.StandardOutput.ReadToEnd();
if (process.ExitCode != 0) {
}