Unity 调用外部exe的完美封装
手写不易,点赞支持,支持纯手工,转载请标明出处
using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using UnityEngine; public class ExecuteEXE { 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> message; private Thread thread; private Process process; /// <summary> /// 对外输出message,消息在update里轮询,后期维护的成本要比用委托低 /// </summary> public Message GetMessage() { lock (locker) { if (message == null || message.Count <= 0) { return null; } return message.Dequeue(); } } /// <summary> /// 异步执行exe /// </summary> public void AsyncExecute(string exePath, params string[] args) { ForceDispose(); thread = new Thread(() => { try { 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")); } else { 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(); } /// <summary> /// 强制释放所有内容 /// </summary> /// <returns></returns> public bool ForceDispose() { bool processError = ForceDisposeProcess(); bool threadError = ForceDisposeThread(); ForceDisposeMessage(); return processError || threadError; } /// <summary> /// 添加消息 /// </summary> void AddMessage(State state, string msg) { lock (locker) { if (message == null) { message = new Queue<Message>(); } Message m = new Message() { state = state, msg = msg, stack = new StackTrace(true) }; message.Enqueue(m); } } /// <summary> /// 强制释放线程 /// </summary> bool ForceDisposeThread() { bool isError = false; if (thread == null || !thread.IsAlive) { return isError; } try { thread.Abort(); } catch (System.Exception e) { AddMessage(State.ThreadMessage, "Thread Abort Error:" + e.Message); isError = true; } return isError; } /// <summary> /// 强制释放进程 /// </summary> bool ForceDisposeProcess() { bool isError = false; if (process == null) { return isError; } try { process.Close(); process.Dispose(); } catch (System.Exception e) { AddMessage(State.ProcessMessage, "Process Dispose Error:" + e.Message); isError = true; } return isError; } /// <summary> /// 释放消息队列 /// </summary> private void ForceDisposeMessage() { lock (locker) { if (message != null) { message.Clear(); } message = null; } } }
博客园Jason_c微信打赏码
如果本篇文档对你有帮助,打赏Jason_c根华子吧,他的私房钱被老婆没收了,呜呜!