forked from lulianqi/MyOutTool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MyWindowsCmd.cs
307 lines (278 loc) · 9.8 KB
/
MyWindowsCmd.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
namespace yourNamespace
{
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[1024];
Stream receiveStream = (Stream)ReceiveStream;
int bytes = receiveStream.Read(read, 0, 1024);
string esc = baseEncode.GetString(new byte[] { 27, 91 });
//string bs = baseEncode.GetString(new byte[] { 8 }); // \b
string re = "";
while (bytes > 0 && !willKill)
{
re = baseEncode.GetString(read, 0, bytes);
if (isDropAscStyle)
{
while (re.Contains(esc))
{
int starEsc = re.IndexOf(esc);
int endEsc = re.IndexOf('m', starEsc);
if (endEsc > 0)
{
re = re.Remove(starEsc, (endEsc - starEsc + 1));
}
else
{
re = re.Remove(starEsc, 2);
}
}
}
PutOutData(re);
bytes = receiveStream.Read(read, 0, 1024);
}
}
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();
}
}
}