使用C#执行命令行程序并异步输出

Posted on 2013-09-23 14:41  逍遥云翳  阅读(2056)  评论(0编辑  收藏  举报

在程序中常常会需要运行命令行程序并获取其运行状态或运行结果,此时则需要使用Process类,最近研究了许多,自感颇有心得,现在分享给大家。

废话少说,上代码:

 1         /// <summary>
 2         /// 运行命令
 3         /// </summary>
 4         /// <param name="command">要运行的命令</param>
 5         /// <param name="timeout">运行命令的超时</param>
 6         /// <param name="standardOutputEncoding">异步输出的编码方式</param>
 7         /// <param name="standardErrorEncoding">异步错误的编码方式</param>
 8         /// <param name="outputHandler">异步输出的委托</param>
 9         /// <param name="errorHandler">异步错误的委托</param>
10         /// <returns></returns>
11         public int RunCommand(string command, int timeout, Encoding standardOutputEncoding, Encoding standardErrorEncoding, DataReceivedEventHandler outputHandler, DataReceivedEventHandler errorHandler)
12         {
13             int exitCode = -1;
14             using (Process cmdProcess = new Process())
15             {
16                 //在Windows中使用cmd /c [command]的方式可以运行绝大多数的命令行程序
17                 cmdProcess.StartInfo.FileName = "cmd.exe";
18                 cmdProcess.StartInfo.Arguments = "/c " + command;
19                 //若要使用异步输出则必须不使用操作系统外壳
20                 cmdProcess.StartInfo.UseShellExecute = false;
21                 //打开输出重定向
22                 cmdProcess.StartInfo.RedirectStandardOutput = true;
23                 //打开错误重定向
24                 cmdProcess.StartInfo.RedirectStandardError = true;
25                 //若要使用异步输出则必须不创建新窗口
26                 cmdProcess.StartInfo.CreateNoWindow = true;
27                 //以下两行指定了输出使用的编码方式,Process将使用指定的编码方式解码输出流。
28                 //若删除以下两行则Process会使用默认ANSI编码页解码输出流
29                 //指定异步输出使用的编码方式
30                 cmdProcess.StartInfo.StandardOutputEncoding = standardOutputEncoding;
31                 //指定异步错误使用的编码方式
32                 cmdProcess.StartInfo.StandardErrorEncoding = standardErrorEncoding;
33                 //将输出处理函数重定向到输出处理委托
34                 cmdProcess.OutputDataReceived += outputHandler;
35                 //将错误处理函数重定向到错误处理委托
36                 cmdProcess.ErrorDataReceived += errorHandler;
37                 //启动控制台进程
38                 cmdProcess.Start();
39                 //开始异步读取输出流
40                 cmdProcess.BeginOutputReadLine();
41                 //开始异步读取错误流
42                 cmdProcess.BeginErrorReadLine();
43                 //等待进程退出
44                 //timeout为等待的毫秒数
45                 //若timeout为负则会无限期等待
46                 cmdProcess.WaitForExit(timeout);
47                 //结束异步读取错误流
48                 cmdProcess.CancelErrorRead();
49                 //结束异步读取输出流
50                 cmdProcess.CancelOutputRead();
51                 //若进程正常退出则将退出码置为进程退出码,否则置为超时码
52                 if (cmdProcess.HasExited)
53                 {
54                     exitCode = cmdProcess.ExitCode;
55                 }
56                 else
57                 {
58                     exitCode = -2;
59                 }
60                 //清理进程使用的资源
61                 cmdProcess.Close();
62             }
63             return exitCode;
64         }


使用这种方法运行命令行程序时,为了方法的简洁性,没有对输入流做处理。若多次调用本方法则会为每次调用启动一个进程,进程之间没有相关性,若有童鞋需要在同一进程中执行多条命令,则可以参考一下方案:

  1. 为cmdProcess重定向输入
  2. 将需要执行的多条命令写成一个bat文件,然后执行bat文件
  3. 若运行的命令行程序支持的话可以使用<重定向输入

您需要为outputHandler和errorHandler提供一个符合DataReceivedEventHandler的委托,此委托可以为null

在调用时可以使用匿名委托以将所有输出添加到一个List中。

参考连接:

  1. Process类:http://msdn.microsoft.com/zh-cn/library/vstudio/System.Diagnostics.Process.aspx
  2. OutputDataReceived 事件:http://msdn.microsoft.com/zh-cn/library/vstudio/system.diagnostics.process.outputdatareceived.aspx
  3. 重定向输入:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.processstartinfo.redirectstandardinput(v=vs.85).aspx
  4. 标准输出的首选编码:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.processstartinfo.standardoutputencoding(v=vs.85).aspx

 

Copyright © 2024 逍遥云翳
Powered by .NET 8.0 on Kubernetes