zoukankan      html  css  js  c++  java
  • 调用CMD命令的一个.NET工具类(MyWindowsCmd)

    功能大概描述一下如果直接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 * 内容摘要: mycllq@hotmail.com
     15 * 
     16 * 历史记录:
     17 * 日      期:   201601212          创建人: lulianqi mycllq@hotmail.com
     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 });    //  
    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 }

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

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

  • 相关阅读:
    java值类型和引用类型
    0513作业
    随机四位验证码
    1-36随机生成6个不重复的数
    java随机数
    0509作业
    作业0508
    字符集
    eclipse快捷键
    数据类型 转换
  • 原文地址:https://www.cnblogs.com/lulianqi/p/6180479.html
Copyright © 2011-2022 走看看