Process.start:如何获得输出?

我想从我的Mono / .NET应用程序运行外部命令行程序。 例如,我想运行mencoder 。 可能吗:

  1. 获取命令行shell输出,并将其写在我的文本框?
  2. 获取数值显示随着时间stream逝的进度条?

当您创build您的Process对象适当地设置StartInfo

 var proc = new Process { StartInfo = new ProcessStartInfo { FileName = "program.exe", Arguments = "command line arguments to your executable", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true } }; 

然后启动过程并从中读取:

 proc.Start(); while (!proc.StandardOutput.EndOfStream) { string line = proc.StandardOutput.ReadLine(); // do something with line } 

您可以使用int.Parse()int.TryParse()将string转换为数字值。 如果读取的string中有无效的数字字符,则可能必须先执行一些string操作。

您可以同步asynchronous处理输出。

1:同步示例

 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(); } 

请注意 ,最好处理输出错误 :它们必须分开处理。

(*)对于某些命令(这​​里是StartInfo.Arguments ),您必须添加/c 指令 ,否则该进程在WaitForExit()中冻结。

2:asynchronous的例子

 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); } 

如果您不需要对输出执行复杂的操作,则可以绕过OutputHandler方法,直接添加内联处理程序:

 //* Set your output and error (asynchronous) handlers process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data); process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data); 

标准的.NET方法是从Process的StandardOutputstream中读取数据。 链接的MSDN文档中有一个示例。 类似的,您可以从StandardError中读取数据,并写入StandardInput 。

好吧,对于任何需要错误和输出的人来说,读取其他解决scheme时遇到的问题都会死锁,这是我在阅读StandardOutput属性的MSDN解释之后所build立的解决scheme。

答案是基于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); } 

你可以使用共享内存的2个进程通信,检查出MemoryMappedFile

您将主要在父进程中使用“using”语句创build一个内存映射文件mmf ,然后创build第二个进程直到它终止,并让它使用BinaryWriter将结果写入到mmf ,然后使用父进程从mmf读取结果,您也可以使用命令行parameter passingmmf名称或硬编码它。

确保在父进程中使用映射文件时,在父进程中释放映射文件之前,使subprocess将结果写入映射文件

例如:父进程

  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(); } 

subprocess

  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(); } 

要使用这个示例,您需要创build一个包含2个项目的解决scheme,然后从%childDir%/ bin / debug中获取subprocess的生成结果,并将其复制到%parentDirectory%/ bin / debug,然后运行父项目

childDirparentDirectory是你的项目在PC上的文件夹名称好运:)

  1. 可以按照此处所述获取进程的命令行shell输出: http : //www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx

  2. 这取决于mencoder。 如果它在命令行上输出这个状态,那么是的:)