private ExecuteEXE() { } private static ExecuteEXE instance; public static ExecuteEXE Instance { get { if (instance==null) instance = new ExecuteEXE(); return instance; public enum State Success=0,//总状态 Failure, Error,//出错了 ThreadMessage =100,//线程信息 ProcessMessage =200,//进程信息 public class Message public State state;//状态码 public string msg;//消息 public StackTrace stack;//堆栈 private static readonly object locker = new object(); private readonly string logFilter = "- INFO:"; private readonly int timeoutMs = 60 * 1000;//进程超时时间,毫秒 private Queue message; private Thread thread; private Process process; /// /// 对外输出message,消息在update里轮询,后期维护的成本要比用委托低 /// public Message GetMessage() lock (locker) if (message == null || message.Count <= 0) return null; return message.Dequeue(); /// /// 异步执行exe /// public void AsyncExecute(string exePath, params string[] args) ForceDispose(); thread = new Thread(() => process = new Process(); process.StartInfo.CreateNoWindow = true; process.StartInfo.ErrorDialog = false; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardInput = false; process.StartInfo.StandardOutputEncoding = Encoding.UTF8; process.StartInfo.StandardErrorEncoding = Encoding.UTF8; process.StartInfo.FileName = exePath; if (args != null && args.Length > 0) foreach (var arg in args) process.StartInfo.Arguments += " " + arg; process.OutputDataReceived += new DataReceivedEventHandler((s, e) => //过滤掉INFO级别的日志 if (e != null && e.Data != null && !e.Data.Contains(logFilter)) AddMessage(State.ProcessMessage, e.Data); process.ErrorDataReceived += new DataReceivedEventHandler((s, e) => if (e != null && e.Data != null) AddMessage(State.Error, e.Data); process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); bool isFinish=process.WaitForExit(timeoutMs); int timeoutCode = -999999;//isFinish=false时,表示进程超时 int exitCode = isFinish ? process.ExitCode : timeoutCode; System.DateTime startTime = isFinish ? process.StartTime : System.DateTime.Now; System.DateTime exitTime = isFinish ? process.ExitTime : System.DateTime.Now;//isFinish=false时,调用ExitCode,ExitTime会抛出异常:Process must exit before requested information can be determined. process.Close(); process.Dispose(); process = null; if (exitCode == timeoutCode) AddMessage(State.Error, "进程超时"); else if (exitCode == 0) AddMessage(State.Success, "完成,进程ExitCode:" + exitCode + ",StartTime:" + startTime.ToString("yyyy-MM-dd HH:mm:ss.fff") + ",ExitTime:" + exitTime.ToString("yyyy-MM-dd HH:mm:ss.fff")); AddMessage(State.Failure, "失败,进程ExitCode:" + exitCode + ",StartTime:" + startTime.ToString("yyyy-MM-dd HH:mm:ss.fff") + ",ExitTime:" + exitTime.ToString("yyyy-MM-dd HH:mm:ss.fff")); catch (System.Exception e) AddMessage(State.Error, "进程异常:" + e.Message); thread.Start(); /// /// 强制释放所有内容 /// /// public bool ForceDispose() bool processError = ForceDisposeProcess(); bool threadError = ForceDisposeThread(); ForceDisposeMessage(); return processError || threadError; /// /// 添加消息 /// void AddMessage(State state, string msg) lock (locker) if (message == null) message = new Queue(); Message m = new Message() state = state, msg = msg, stack = new StackTrace(true) message.Enqueue(m); /// /// 强制释放线程 /// bool ForceDisposeThread() bool isError = false; if (thread == null || !thread.IsAlive) return isError; thread.Abort(); catch (System.Exception e) AddMessage(State.ThreadMessage, "Thread Abort Error:" + e.Message); isError = true; return isError; /// /// 强制释放进程 /// bool ForceDisposeProcess() bool isError = false; if (process == null) return isError; process.Close(); process.Dispose(); catch (System.Exception e) AddMessage(State.ProcessMessage, "Process Dispose Error:" + e.Message); isError = true; return isError; /// /// 释放消息队列 /// private void ForceDisposeMessage() lock (locker) if (message != null) message.Clear(); message = null;