调用CMD命令的一个.NET工具类

功能大概描述一下如果直接StandardOutput.ReadToEnd()这种方法,有很多限制

这类方式必须把命令全部执行一次写入并标记为exit,而且返回内容的获取会一直等待,如果在主线程里使用会导致假死。

若遇到执行时间长,同时会在执行中输出进度的命令,则明显不适应

对于部分特殊字符这类方法会直接中断一直等待(特别是对包含asc颜色等样式的输出)

本文的工具类解决以上问题,使用委托订阅的方式即时的输出执行过程,不用等待,异步输出结算后自动退出

方便应对类似这种需要长时间运行即时输出的打包命令。

下面直接贴出代码,方便后面的朋友 直接使用。

前一个类StreamAsynRead是用于读取cmd进程返回流IO 后面的MyWindowsCmd为cmd主要功能

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5
  6 using System.IO;
  7 using System.Threading;
  8
  9 /*******************************************************************************
 10 * Copyright (c) 2016 lulianqi
 11 * All rights reserved.
 12 *
 13 * 文件名称:
 14 * 内容摘要: [email protected]
 15 *
 16 * 历史记录:
 17 * 日      期:   201601212          创建人: lulianqi [email protected]
 18 * 描    述: 创建
 19 *******************************************************************************/
 20
 21 namespace yourNamespaceName
 22 {
 23     class StreamAsynRead:IDisposable
 24     {
 25         public delegate void delegateGetStreamAsynReadEventHandler(object sender, string outData);
 26         public event delegateGetStreamAsynReadEventHandler OnGetAsynReadData;
 27
 28         private Stream baseStream;
 29         private Thread readStreamThread;
 30         private Encoding baseEncode;
 31         private bool isDropAscStyle;
 32         private bool willKill;
 33
 34         /// <summary>
 35         /// 异步读取指定IO流并即时返回直到该流结束(初始化完成后即开始读取)
 36         /// </summary>
 37         /// <param name="yourBaseStream">目标IO流</param>
 38         /// <param name="yourEncode">编码方式</param>
 39         /// <param name="dropAscStyle">是否丢弃ASC样式</param>
 40         /// <param name="yourGetAsynReadData">数据返回委托</param>
 41         public StreamAsynRead(Stream yourBaseStream, Encoding yourEncode, bool dropAscStyle , delegateGetStreamAsynReadEventHandler yourGetAsynReadData)
 42         {
 43             if (yourBaseStream == null)
 44             {
 45                 throw new Exception("yourBaseStream is null");
 46             }
 47             else
 48             {
 49                 isDropAscStyle = dropAscStyle;
 50                 baseStream = yourBaseStream;
 51                 baseEncode = yourEncode;
 52                 OnGetAsynReadData += yourGetAsynReadData;
 53                 StartRead();
 54                 willKill = false;
 55             }
 56         }
 57
 58         public StreamAsynRead(Stream yourBaseStream, Encoding yourEncode, delegateGetStreamAsynReadEventHandler yourGetAsynReadData)
 59             : this(yourBaseStream, yourEncode, false, yourGetAsynReadData){}
 60
 61         public StreamAsynRead(Stream yourBaseStream, delegateGetStreamAsynReadEventHandler yourGetAsynReadData)
 62             : this(yourBaseStream, ASCIIEncoding.UTF8, false, yourGetAsynReadData) { }
 63
 64         public bool IsdropAscStyle
 65         {
 66             get { return isDropAscStyle; }
 67             set { isDropAscStyle = value; }
 68         }
 69
 70
 71         private void PutOutData(string yourData)
 72         {
 73             if(OnGetAsynReadData!=null)
 74             {
 75                 this.OnGetAsynReadData(this, yourData);
 76             }
 77         }
 78
 79         private bool StartRead()
 80         {
 81             if(baseStream==null)
 82             {
 83                 return false;
 84             }
 85             if(readStreamThread!=null)
 86             {
 87                 if (readStreamThread.IsAlive)
 88                 {
 89                     readStreamThread.Abort();
 90                 }
 91             }
 92             readStreamThread = new Thread(new ParameterizedThreadStart(GetDataThread));
 93             readStreamThread.IsBackground = true;
 94             readStreamThread.Start(baseStream);
 95             return true;
 96         }
 97
 98         private void GetDataThread(object ReceiveStream)
 99         {
100             /*
101             try
102             {
103             }
104             catch (ThreadAbortException abortException)
105             {
106                 Console.WriteLine((string)abortException.ExceptionState);
107             }
108              * */
109
110             Byte[] read = new Byte[1024];
111             Stream receiveStream = (Stream)ReceiveStream;
112             int bytes = receiveStream.Read(read, 0, 1024);
113             string esc = baseEncode.GetString(new byte[] { 27, 91 });
114             //string bs = baseEncode.GetString(new byte[] { 8 });    //  \b
115             string re = "";
116             while (bytes > 0 && !willKill)
117             {
118                 re = baseEncode.GetString(read, 0, bytes);
119                 if (isDropAscStyle)
120                 {
121                     while (re.Contains(esc))
122                     {
123                         int starEsc = re.IndexOf(esc);
124                         int endEsc = re.IndexOf(‘m‘, starEsc);
125                         if (endEsc > 0)
126                         {
127                             re = re.Remove(starEsc, (endEsc - starEsc + 1));
128                         }
129                         else
130                         {
131                             re = re.Remove(starEsc, 2);
132                         }
133                     }
134                 }
135                 PutOutData(re);
136                 bytes = receiveStream.Read(read, 0, 1024);
137             }
138         }
139
140         public void Dispose()
141         {
142             willKill = true;
143         }
144     }
145
146     class MyWindowsCmd : IDisposable
147     {
148         public enum RedirectOutputType
149         {
150             RedirectStandardInput,
151             RedirectStandardError
152         }
153
154         public delegate void delegateGetCmdMessageEventHandler(object sender, string InfoMessage, RedirectOutputType redirectOutputType);
155         /// <summary>
156         /// 订阅CMD返回数据
157         /// </summary>
158         public event delegateGetCmdMessageEventHandler OnGetCmdMessage;
159
160         private System.Diagnostics.Process p = new System.Diagnostics.Process();
161         StreamAsynRead standardOutputRead = null;
162         StreamAsynRead standardErrorRead = null;
163         private string errorMes = null;
164         private string cmdName = null;
165         private bool isStart = false;
166         private bool isDropAscStyle = false;
167
168
169         public MyWindowsCmd()
170         {
171             p.StartInfo.FileName = "cmd.exe";
172             cmdName = "CMD";
173             p.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
174             p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
175             p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
176             p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
177             p.StartInfo.CreateNoWindow = true;//不显示程序窗口
178             p.StartInfo.ErrorDialog = true;
179         }
180
181         /// <summary>
182         /// 含名称字段的构造函数
183         /// </summary>
184         /// <param name="yourNmae">CMD名称(方便区分多份CMD实例)</param>
185         public MyWindowsCmd(string yourNmae):this()
186         {
187             cmdName = yourNmae;
188         }
189
190         private void ShowMessage(string mes, RedirectOutputType redirectOutputType)
191         {
192             if (OnGetCmdMessage != null)
193             {
194                 this.OnGetCmdMessage(this, mes, redirectOutputType);
195             }
196         }
197
198         /// <summary>
199         /// 获取CMD名称
200         /// </summary>
201         public string CmdName
202         {
203             get { return cmdName; }
204         }
205
206         /// <summary>
207         /// 获取最近的错误
208         /// </summary>
209         public string ErrorMes
210         {
211             get { return errorMes; }
212         }
213
214         /// <summary>
215         /// 获取一个值,盖值指示该CMD是否启动
216         /// </summary>
217         public bool IsStart
218         {
219             get { return isStart; }
220         }
221
222         /// <summary>
223         /// 获取或设置获取内容回调时是否丢弃ASK颜色等样式方案(如果您的应用不具备处理这种样式的功能,请选择放弃该样式)
224         /// </summary>
225         public bool IsDropAscStyle
226         {
227             get { return isDropAscStyle; }
228             set { isDropAscStyle = value; }
229         }
230
231         /// <summary>
232         /// 启动CMD
233         /// </summary>
234         /// <returns>是否成功启动</returns>
235         public bool StartCmd()
236         {
237             if(isStart)
238             {
239                 errorMes = "[StartCmd]" + "is Already Started";
240                 return false;
241             }
242             try
243             {
244                 p.Start();//启动程序
245                 //System.Text.Encoding.GetEncoding("gb1232");
246                 if (standardOutputRead!=null)
247                 {
248                     standardOutputRead.Dispose();
249                 }
250                 if (standardErrorRead!=null)
251                 {
252                     standardErrorRead.Dispose();
253                 }
254                 standardOutputRead = new StreamAsynRead(p.StandardOutput.BaseStream, System.Text.Encoding.Default, true, new StreamAsynRead.delegateGetStreamAsynReadEventHandler((obj, str) => { this.OnGetCmdMessage(this, str, RedirectOutputType.RedirectStandardInput); }));
255                 standardErrorRead = new StreamAsynRead(p.StandardError.BaseStream, System.Text.Encoding.Default, true, new StreamAsynRead.delegateGetStreamAsynReadEventHandler((obj, str) => { this.OnGetCmdMessage(this, str, RedirectOutputType.RedirectStandardError); }));
256                 isStart = true;
257                 return true;
258             }
259             catch (Exception ex)
260             {
261                 errorMes = "[StartCmd]" + ex.Message;
262                 return false;
263             }
264         }
265
266         /// <summary>
267         /// 执行CMD命令
268         /// </summary>
269         /// <param name="yourCmd">cmd命令内容</param>
270         /// <returns>是否成功</returns>
271         public bool RunCmd(string yourCmd)
272         {
273             if(yourCmd==null || !isStart)
274             {
275                 return false;
276             }
277             try
278             {
279                 p.StandardInput.WriteLine(yourCmd);
280                 return true;
281             }
282             catch(Exception ex)
283             {
284                 errorMes = "[RunCmd]" + ex.Message;
285                 return false;
286             }
287         }
288
289         /// <summary>
290         /// 等待执行完成(同步方法,请勿在主线程中调用)
291         /// </summary>
292         public void WaitForExit()
293         {
294             if (RunCmd("exit"))
295             {
296                 p.WaitForExit();
297             }
298         }
299
300         /// <summary>
301         /// 停止该CMD,如果不准备再次启动,请直接调用Dispose
302         /// </summary>
303         public void StopCmd()
304         {
305             if(isStart)
306             {
307                 p.Close();
308                 isStart = false;
309             }
310         }
311
312         public void Dispose()
313         {
314             StopCmd();
315             standardOutputRead.Dispose();
316             standardErrorRead.Dispose();
317         }
318     }
319 }

因为主要也是为了满足自己的需要,肯定还有很多错误或不合理的地方。

发现任何错误或任何问题及建议,也感谢在下面留言

时间: 2024-10-12 09:04:52

调用CMD命令的一个.NET工具类的相关文章

Java调用cmd命令 打开一个站点

使用Java程序打开一个站点 近期做了个东西使用SWT技术在一个client程序 须要升级时在提示升级 点击窗口上的一个连接 打开下载网页 花费了我非常长时间 用到了把它记录下来  怕是忘记,须要时能够直接来用到.         try { //不是在Java程序中运行而是在操作系统中运行             Runtime.getRuntime().exec("cmd /c start http://blog.csdn.net/blogluoqi/"); //Runtime.g

PHP 命令行参数解析工具类

<?php /** * 命令行参数解析工具类 * @author guolinchao */ class CommandLine { // 临时记录短选项的选项值 private static $shortOptVal = null; // options value private static $optsArr = array(); // command args private static $argsArr = array(); // 是否已解析过命令行参数 private static

客户端调用 CMD 命令并回显结果。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; using Syste

h5页面调用cmd命令并隐藏cmd弹窗

js代码 /*** 通过js调用cmd命令利用ffmpeg实现录屏或者录像功能 ***/ var  cmd = new ActiveXObject("WScript.Shell"); /* 命令参数说明 cmd.exe /c dir 是执行完dir命令后关闭命令窗口. cmd.exe /k dir 是执行完dir命令后不关闭命令窗口. cmd.exe /c start dir 会打开一个新窗口后执行dir指令,原窗口会关闭. cmd.exe /k start dir 会打开一个新窗口后

JAVA中调用CMD命令,并输出执行结果

package com.wzw.util; import java.io.BufferedReader; import java.io.InputStreamReader; public class CmdDemo { public static void main(String[] args) { BufferedReader br = null; try { Process p = Runtime.getRuntime().exec("net user"); br = new Bu

用接口实现的一个pdo工具类

<?php //定义一个pdo工具类 class DAOPdo implements I_Dao { //配置信息 private $_host; private $_root; private $_dbname; private $_pw; private $_port; private $_charset; //pdo对象 private $pdo; //pdo结果集对象 private $result; //被影响的记录数 private $affected_row; //当前类的实例化对

转:Java调用CMD命令

java的Runtime.getRuntime().exec(commandStr)可以调用执行cmd指令. cmd /c dir 是执行完dir命令后关闭命令窗口. cmd /k dir 是执行完dir命令后不关闭命令窗口. cmd /c start dir 会打开一个新窗口后执行dir指令,原窗口会关闭. cmd /k start dir 会打开一个新窗口后执行dir指令,原窗口不会关闭. 可以用cmd /?查看帮助信息. ★CMD命令★ 1. gpedit.msc-----组策略 2. s

调用cmd命令行命令(借鉴)

留待以后观看 ---------------------------------------------------------------------------- public class IP_MAC_TypeHelper { /** * 控制台执行arp -a命令 * * @return * */ public static InputStream getInputStream() { Runtime rt = Runtime.getRuntime(); InputStream in =

测试:python调用cmd命令三种方法

目前我使用到的python中执行cmd的方式有三种 使用os.system("cmd") 该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码,即脚本中"exit 1"的代码执行后,os.system函数返回值的高位数则是1,如果低位数是0的情况下,则函数的返回值是0×100,换算为10进制得到256. 如果我们需要获得os.system的正确返回值,那使用位移运算可以还原返回值: >>>