Process.start:如何获得输出?
我想从我的Mono / .NET应用程序运行外部命令行程序。 例如,我想运行mencoder 。 可能吗:
- 获取命令行shell输出,并将其写在我的文本框?
- 获取数值显示随着时间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,然后运行父项目
childDir
和parentDirectory
是你的项目在PC上的文件夹名称好运:)
-
可以按照此处所述获取进程的命令行shell输出: http : //www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx
-
这取决于mencoder。 如果它在命令行上输出这个状态,那么是的:)