调用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 ...
随机推荐
- 在没有DOM操作的日子里,我是怎么熬过来的(上)
前言 在我动笔写这篇文章的时候,我刚刚从我的项目中删除了最后一行JQuery代码.至于我为何要这么做,请听闰土娓娓道来.前几年我还在想,假如有一天,前端世界里不能再直接操作dom了,我该怎么办?没想到 ...
- Spring Boot 的Maven多模块开发web项目使用外部容器进行部署
Spring Boot中自带有Tomcat容器,因此Spring Boot项目只需要运行main函数,就可以运行,但是以往的web项目,我们习惯于使用自己安装的Tomcat运行或者使用Tomcat.J ...
- jquery无new构建学习笔记
当我们想要创建一个对象,我们可能使用new方法去构建一个对象,那按道理jquery也是一个对象,应该也是用new jquery()来构建呀为什么我们创建jquery对象不用new jquery()而是 ...
- 读取不标准的JSON数据
正常的JSON数据 [ {"key":"UI","value":"UII"}, {"key ...
- NYOJ 323 Drainage Ditches 网络流 FF 练手
Drainage Ditches 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 Every time it rains on Farmer John's fields, ...
- 关于pipelineDB调用GetLocalStreamReaders的BUG
如果想获取一个stream所有的reader,那么必须调用这个函数: Bitmapset *targets = GetLocalStreamReaders(relid); 如果stream下面没有re ...
- OAuth 2.0(网转)
(一)背景知识 OAuth 2.0很可能是下一代的"用户验证和授权"标准,目前在国内还没有很靠谱的技术资料.为了弘扬"开放精神",让业内的人更容易理解" ...
- NOIP2017 小凯的疑惑
题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的.现在小 凯想知道在无法准确支付的物品中,最贵的 ...
- Linux中MySQL5.6编译安装与MySQL5.7二进制安装步骤
首先,介绍一下MySQL的几种安装方式 1.RPM.Yum 的安装方式:安装方便.安装速度快,无法定制 2.二进制:不需要安装,解压即可使用,不能定制功能 3.编译安装:可定制,安装慢. 编译安装中需 ...
- 》》canvas时钟
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...