如何从C#执行命令行程序并返回STD OUT结果.具体来说,我想对以编程方式选择的两个文件执行DIFF,并将结果写入文本框.是的,我可以为自己解决这个问题,但肯定有人做过类似的事情,我很懒...
// Start the child process. Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "YOURBATCHFILE.bat"; p.Start(); // Do not wait for the child process to exit before // reading to the end of its redirected stream. // p.WaitForExit(); // Read the output stream first and then wait. string output = p.StandardOutput.ReadToEnd(); p.WaitForExit();
代码来自MSDN.
这是一个快速示例:
//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();
还有一个我发现有用的参数,我用它来消除进程窗口
pProcess.StartInfo.CreateNoWindow = true;
这有助于完全隐藏黑色控制台窗口,如果这是你想要的.
// 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) + "'"; }
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(@"program_to_call.exe"); psi.RedirectStandardOutput = true; psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; psi.UseShellExecute = false; System.Diagnostics.Process proc System.Diagnostics.Process.Start(psi);; System.IO.StreamReader myOutput = proc.StandardOutput; proc.WaitForExit(2000); if (proc.HasExited) { string output = myOutput.ReadToEnd(); }
此页面上接受的答案有一个在极少数情况下很麻烦的弱点.有两个文件句柄,程序按惯例,stdout和stderr写入.如果您只是读取单个文件句柄(例如Ray的答案),并且您正在开始的程序将足够的输出写入stderr,它将填充输出stderr缓冲区并阻塞.然后你的两个进程陷入僵局.缓冲区大小可以是4K.这在短期程序中极为罕见,但如果你有一个长期运行的程序,它反复输出到stderr,它最终会发生.调试和跟踪这很棘手.
有几种很好的方法可以解决这个问题.
一种方法是执行cmd.exe而不是程序,并使用cmd.exe的/ c参数调用程序以及cmd.exe的"2>&1"参数,告诉它合并stdout和stderr.
var p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
另一种方法是使用一个同时读取两个句柄的编程模型.
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();
您将需要使用ProcessStartInfo
与RedirectStandardOutput
启用-那么你可以读取输出流.您可能会发现使用">"将输出重定向到文件(通过操作系统)更容易,然后只需读取文件即可.
[编辑:像雷一样:+1]