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

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

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

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

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

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

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

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

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.IO;
using System.Threading; /*******************************************************************************
* Copyright (c) 2016 lulianqi
* All rights reserved.
*
* 文件名称:
* 内容摘要: mycllq@hotmail.com
*
* 历史记录:
* 日 期: 201601212 创建人: lulianqi mycllq@hotmail.com
* 描 述: 创建
*******************************************************************************/ namespace yourNamespaceName
{
class StreamAsynRead:IDisposable
{
public delegate void delegateGetStreamAsynReadEventHandler(object sender, string outData);
public event delegateGetStreamAsynReadEventHandler OnGetAsynReadData; private Stream baseStream;
private Thread readStreamThread;
private Encoding baseEncode;
private bool isDropAscStyle;
private bool willKill; /// <summary>
/// 异步读取指定IO流并即时返回直到该流结束(初始化完成后即开始读取)
/// </summary>
/// <param name="yourBaseStream">目标IO流</param>
/// <param name="yourEncode">编码方式</param>
/// <param name="dropAscStyle">是否丢弃ASC样式</param>
/// <param name="yourGetAsynReadData">数据返回委托</param>
public StreamAsynRead(Stream yourBaseStream, Encoding yourEncode, bool dropAscStyle , delegateGetStreamAsynReadEventHandler yourGetAsynReadData)
{
if (yourBaseStream == null)
{
throw new Exception("yourBaseStream is null");
}
else
{
isDropAscStyle = dropAscStyle;
baseStream = yourBaseStream;
baseEncode = yourEncode;
OnGetAsynReadData += yourGetAsynReadData;
StartRead();
willKill = false;
}
} public StreamAsynRead(Stream yourBaseStream, Encoding yourEncode, delegateGetStreamAsynReadEventHandler yourGetAsynReadData)
: this(yourBaseStream, yourEncode, false, yourGetAsynReadData){} public StreamAsynRead(Stream yourBaseStream, delegateGetStreamAsynReadEventHandler yourGetAsynReadData)
: this(yourBaseStream, ASCIIEncoding.UTF8, false, yourGetAsynReadData) { } public bool IsdropAscStyle
{
get { return isDropAscStyle; }
set { isDropAscStyle = value; }
} private void PutOutData(string yourData)
{
if(OnGetAsynReadData!=null)
{
this.OnGetAsynReadData(this, yourData);
}
} private bool StartRead()
{
if(baseStream==null)
{
return false;
}
if(readStreamThread!=null)
{
if (readStreamThread.IsAlive)
{
readStreamThread.Abort();
}
}
readStreamThread = new Thread(new ParameterizedThreadStart(GetDataThread));
readStreamThread.IsBackground = true;
readStreamThread.Start(baseStream);
return true;
} private void GetDataThread(object ReceiveStream)
{
/*
try
{
}
catch (ThreadAbortException abortException)
{
Console.WriteLine((string)abortException.ExceptionState);
}
* */ Byte[] read = new Byte[];
Stream receiveStream = (Stream)ReceiveStream;
int bytes = receiveStream.Read(read, , );
string esc = baseEncode.GetString(new byte[] { , });
//string bs = baseEncode.GetString(new byte[] { 8 }); // \b
string re = "";
while (bytes > && !willKill)
{
re = baseEncode.GetString(read, , bytes);
if (isDropAscStyle)
{
while (re.Contains(esc))
{
int starEsc = re.IndexOf(esc);
int endEsc = re.IndexOf('m', starEsc);
if (endEsc > )
{
re = re.Remove(starEsc, (endEsc - starEsc + ));
}
else
{
re = re.Remove(starEsc, );
}
}
}
PutOutData(re);
bytes = receiveStream.Read(read, , );
}
} public void Dispose()
{
willKill = true;
}
} class MyWindowsCmd : IDisposable
{
public enum RedirectOutputType
{
RedirectStandardInput,
RedirectStandardError
} public delegate void delegateGetCmdMessageEventHandler(object sender, string InfoMessage, RedirectOutputType redirectOutputType);
/// <summary>
/// 订阅CMD返回数据
/// </summary>
public event delegateGetCmdMessageEventHandler OnGetCmdMessage; private System.Diagnostics.Process p = new System.Diagnostics.Process();
StreamAsynRead standardOutputRead = null;
StreamAsynRead standardErrorRead = null;
private string errorMes = null;
private string cmdName = null;
private bool isStart = false;
private bool isDropAscStyle = false; public MyWindowsCmd()
{
p.StartInfo.FileName = "cmd.exe";
cmdName = "CMD";
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
p.StartInfo.CreateNoWindow = true;//不显示程序窗口
p.StartInfo.ErrorDialog = true;
} /// <summary>
/// 含名称字段的构造函数
/// </summary>
/// <param name="yourNmae">CMD名称(方便区分多份CMD实例)</param>
public MyWindowsCmd(string yourNmae):this()
{
cmdName = yourNmae;
} private void ShowMessage(string mes, RedirectOutputType redirectOutputType)
{
if (OnGetCmdMessage != null)
{
this.OnGetCmdMessage(this, mes, redirectOutputType);
}
} /// <summary>
/// 获取CMD名称
/// </summary>
public string CmdName
{
get { return cmdName; }
} /// <summary>
/// 获取最近的错误
/// </summary>
public string ErrorMes
{
get { return errorMes; }
} /// <summary>
/// 获取一个值,盖值指示该CMD是否启动
/// </summary>
public bool IsStart
{
get { return isStart; }
} /// <summary>
/// 获取或设置获取内容回调时是否丢弃ASK颜色等样式方案(如果您的应用不具备处理这种样式的功能,请选择放弃该样式)
/// </summary>
public bool IsDropAscStyle
{
get { return isDropAscStyle; }
set { isDropAscStyle = value; }
} /// <summary>
/// 启动CMD
/// </summary>
/// <returns>是否成功启动</returns>
public bool StartCmd()
{
if(isStart)
{
errorMes = "[StartCmd]" + "is Already Started";
return false;
}
try
{
p.Start();//启动程序
//System.Text.Encoding.GetEncoding("gb1232");
if (standardOutputRead!=null)
{
standardOutputRead.Dispose();
}
if (standardErrorRead!=null)
{
standardErrorRead.Dispose();
}
standardOutputRead = new StreamAsynRead(p.StandardOutput.BaseStream, System.Text.Encoding.Default, true, new StreamAsynRead.delegateGetStreamAsynReadEventHandler((obj, str) => { this.OnGetCmdMessage(this, str, RedirectOutputType.RedirectStandardInput); }));
standardErrorRead = new StreamAsynRead(p.StandardError.BaseStream, System.Text.Encoding.Default, true, new StreamAsynRead.delegateGetStreamAsynReadEventHandler((obj, str) => { this.OnGetCmdMessage(this, str, RedirectOutputType.RedirectStandardError); }));
isStart = true;
return true;
}
catch (Exception ex)
{
errorMes = "[StartCmd]" + ex.Message;
return false;
}
} /// <summary>
/// 执行CMD命令
/// </summary>
/// <param name="yourCmd">cmd命令内容</param>
/// <returns>是否成功</returns>
public bool RunCmd(string yourCmd)
{
if(yourCmd==null || !isStart)
{
return false;
}
try
{
p.StandardInput.WriteLine(yourCmd);
return true;
}
catch(Exception ex)
{
errorMes = "[RunCmd]" + ex.Message;
return false;
}
} /// <summary>
/// 等待执行完成(同步方法,请勿在主线程中调用)
/// </summary>
public void WaitForExit()
{
if (RunCmd("exit"))
{
p.WaitForExit();
}
} /// <summary>
/// 停止该CMD,如果不准备再次启动,请直接调用Dispose
/// </summary>
public void StopCmd()
{
if(isStart)
{
p.Close();
isStart = false;
}
} public void Dispose()
{
StopCmd();
standardOutputRead.Dispose();
standardErrorRead.Dispose();
}
}
}

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

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

调用CMD命令的一个.NET工具类(MyWindowsCmd)的更多相关文章

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

    使用Java程序打开一个站点 近期做了个东西使用SWT技术在一个client程序 须要升级时在提示升级 点击窗口上的一个连接 打开下载网页 花费了我非常长时间 用到了把它记录下来  怕是忘记,须要时能 ...

  2. PHP 命令行参数解析工具类

    <?php/** * 命令行参数解析工具类 * @author guolinchao * @email luoyecb@163.com */class CommandLine{ // store ...

  3. java调用kettle的job和transfer工具类

    package com.woaiyitiaocai.util; import java.util.Map; import java.util.UUID; import org.apache.log4j ...

  4. 分享一个Snackbar工具类 SnackbarUtils;

    分享一个Snackbar工具类,源代码也是在Github上面找的,自己做了一下修改: 功能如下: 1:设置Snackbar显示时间长短                 1.1:Snackbar.LEN ...

  5. 使用node自动生成html并调用cmd命令提交代码到仓库

    生成html提交到git仓库 基于目前的express博客,写了一点代码,通过request模块来请求站点,将html保存到coding-pages目录,复制静态文件夹到coding-pages,最后 ...

  6. python调用cmd显示中文乱码及调用cmd命令

    os.system('dir') 解决方法加上 os.system('chcp 65001') ____________________________________________________ ...

  7. java中定义一个CloneUtil 工具类

    其实所有的java对象都可以具备克隆能力,只是因为在基础类Object中被设定成了一个保留方法(protected),要想真正拥有克隆的能力, 就需要实现Cloneable接口,重写clone方法.通 ...

  8. C语言调用Cmd命令以及执行系统软件

    C语言调用Cmd命令以及执行系统软件 http://blog.csdn.net/qq_16814591/article/details/43676377

  9. IE浏览器中使用js调用cmd命令行demo

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

随机推荐

  1. Java学习笔记13---如何理解“子类重写父类方法时,返回值若为类类型,则必须与父类返回值类型相同或为其子类”

    子类重新实现父类的方法称重写:重写时可以修改访问权限修饰符和返回值,方法名和参数类型及个数都不可以修改:仅当返回值为类类型时,重写的方法才可以修改返回值类型,且必须是父类方法返回值的子类:要么就不修改 ...

  2. Bitmap.Config 说明 ALPHA_8 ARGB_4444 ARGB_8888 RGB_565

    这篇文章的目的是了解Bitmap.Config 你可以在使用这个方法的时候会遇到 Bitmap android.graphics.Bitmap.createBitmap(int width, int ...

  3. fragment显示 Binary XML file line #12: Error inflating class fragment 错误

    问题 最近换了新机子,今天在静态用fragment时突然发现闪退,一看显示 Binary XML file line #12: Error inflating class fragment 错误 后面 ...

  4. Android开发过程中使用弱引用解决内存泄露的习惯

    Java虽然有垃圾回收,但是仍然存在内存泄露,比如静态变量.缓存或其他长生命周期的对象引用了其他对象,这些被引用的对象就会长期不能被GC释放,导致内存泄露. 弱引用(WeakReference)是解决 ...

  5. 机器学习算法 - 最近邻规则分类KNN

    上节介绍了机器学习的决策树算法,它属于分类算法,本节我们介绍机器学习的另外一种分类算法:最近邻规则分类KNN,书名为k-近邻算法. 它的工作原理是:将预测的目标数据分别跟样本进行比较,得到一组距离的数 ...

  6. Code Kata:大整数比较大小&大整数四则运算---加减法 javascript实现

    大整数的四则运算已经是老生常谈的问题了.很多的库也已经包含了各种各样的解决方案. 作为练习,我们从最简单的加减法开始. 加减法的核心思路是用倒序数组来模拟一个大数,然后将两个大数的利用竖式进行运算. ...

  7. haproxy,tomcat.apache记录用户真实IP

    Haproxy配置: default加入: option httpclose option forwardfor Tomcat配置: server.xml中添加 prefix="localh ...

  8. python之 json里字典中的value去重

    import simplejson as json with open(r'C:\Users\Desktop\test.txt', 'r' ) as f1, open(r'C:\Users\Deskt ...

  9. 逐步搭建Lamp环境之Linux的运行模式

    首先先来看几个概念,分别是:单用户.单任务.多用户.多任务 单用户: 是指操作系统一般只能由一个人同时进行登录 单任务: 是指操作系统只能同时处理一个任务 多用户: 是指操作系统可以允许由多个用户同时 ...

  10. JAVA IO分析二:字节数组流、基本数据&对象类型的数据流、打印流

    上一节,我们分析了常见的节点流(FileInputStream/FileOutputStream  FileReader/FileWrite)和常见的处理流(BufferedInputStream/B ...