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根华子吧,他的私房钱被老婆没收了,呜呜!
浙公网安备 33010602011771号