调用CMD命令的一个.NET工具类(MyWindowsCmd)
功能大概描述一下如果直接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)的更多相关文章
- Java调用cmd命令 打开一个站点
使用Java程序打开一个站点 近期做了个东西使用SWT技术在一个client程序 须要升级时在提示升级 点击窗口上的一个连接 打开下载网页 花费了我非常长时间 用到了把它记录下来 怕是忘记,须要时能 ...
- PHP 命令行参数解析工具类
<?php/** * 命令行参数解析工具类 * @author guolinchao * @email luoyecb@163.com */class CommandLine{ // store ...
- java调用kettle的job和transfer工具类
package com.woaiyitiaocai.util; import java.util.Map; import java.util.UUID; import org.apache.log4j ...
- 分享一个Snackbar工具类 SnackbarUtils;
分享一个Snackbar工具类,源代码也是在Github上面找的,自己做了一下修改: 功能如下: 1:设置Snackbar显示时间长短 1.1:Snackbar.LEN ...
- 使用node自动生成html并调用cmd命令提交代码到仓库
生成html提交到git仓库 基于目前的express博客,写了一点代码,通过request模块来请求站点,将html保存到coding-pages目录,复制静态文件夹到coding-pages,最后 ...
- python调用cmd显示中文乱码及调用cmd命令
os.system('dir') 解决方法加上 os.system('chcp 65001') ____________________________________________________ ...
- java中定义一个CloneUtil 工具类
其实所有的java对象都可以具备克隆能力,只是因为在基础类Object中被设定成了一个保留方法(protected),要想真正拥有克隆的能力, 就需要实现Cloneable接口,重写clone方法.通 ...
- C语言调用Cmd命令以及执行系统软件
C语言调用Cmd命令以及执行系统软件 http://blog.csdn.net/qq_16814591/article/details/43676377
- IE浏览器中使用js调用cmd命令行demo
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
随机推荐
- 在LwIP 协议栈移植 Snap 7
本文欢迎引用,转载. 引用,转载请标明出处! 调试完毕源码将上传到GitHub 为了嵌入式系统与STEP 7 PLC 通过S7 协议通讯,尝试移植 Snap 7 到STM32F407 cpu 上. 今 ...
- hdoj 4325 Flowers 线段树+离散化
hdoj 4325 Flowers 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4325 思路: 直接线段树,按照花的开放区间的大小建树,要注意虽然 ...
- 最近整理AI相关感想
前言 目前笔者致力于 在AI 开发研究,四大平台里,百度AI 提供 的开发者资料是最全,开发的友好度也是最高的,很多都已经集成在SDK中,支持许多语言体系. 其实 作为公司层面的考虑,针对技术的研究出 ...
- python3 中encode 和decode的使用方法。
编码: 将文本转换成字节流的过程.即Unicode----------->特定格式的编码方式,产生特定的字节流保存在硬盘中(一般为utf-8格式). 解码: 将硬盘中的字节流转换成文本的过程.即 ...
- Aurora 论坛图片下载
Aurora 论坛图片下载是一款快速下载指定网页图片的利器,还可以下载高清原图呢.现支持的网站:①蜂鸟网论坛②中关村摄影论坛③POCO摄影空间④图虫网其他摄影论坛陆续添加中... 效果图: 项目地址: ...
- Git基本使用命令(windows)
1. 记住一个名词repository版本库 =======================基本操作======================== git init 在需要的地方建立一个版本库(也 ...
- 分布式服务Dubbo+Zookeeper安全认证
前言 由于之前的服务都是在内网,Zookeeper集群配置都是走的内网IP,外网不开放相关端口.最近由于业务升级,购置了阿里云的服务,需要对外开放Zookeeper服务. 问题 Zookeeper+d ...
- DDD实践
一. 虽然招聘是主旋律,但技术还是得不断的突破.在.net core的实践中,一开始就瞄准了DDD.需要特别感谢https://github.com/EduardoPires/EquinoxProje ...
- Linux 进程间通信(包含一个经典的生产者消费者实例代码)
前言:编写多进程程序时,有时不可避免的需要在多个进程之间传递数据,我们知道,进程的用户的地址空间是独立,父进程中对数据的修改并不会反映到子进程中,但内核是共享的,大多数进程间通信方式都是在内核中建立一 ...
- DEBUG技巧-设定合适的日志级别
有些技能只有踩过坑的人才能够掌握,能用来避免后来的坑,很多时候是用凌晨的时间换来的,我们通常把他叫做经验. 故事 这个一个关于springmvc的坑的故事. 某天晚上本打算一个小功能分分钟搞定上线,但 ...