using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading.Tasks; using Path = System.IO.Path; namespace ET { public static class ProcessHelper { public static Process Run(string exe, string arguments, string workingDirectory = ".", bool waitExit = false) { //Log.Debug($"Process Run exe:{exe} ,arguments:{arguments} ,workingDirectory:{workingDirectory}"); try { bool redirectStandardOutput = true; bool redirectStandardError = true; bool useShellExecute = false; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { redirectStandardOutput = false; redirectStandardError = false; useShellExecute = true; } if (waitExit) { redirectStandardOutput = true; redirectStandardError = true; useShellExecute = false; } ProcessStartInfo info = new ProcessStartInfo { FileName = exe, Arguments = arguments, CreateNoWindow = true, UseShellExecute = useShellExecute, WorkingDirectory = workingDirectory, RedirectStandardOutput = redirectStandardOutput, RedirectStandardError = redirectStandardError, }; Process process = Process.Start(info); if (waitExit) { WaitExitAsync(process).Coroutine(); } return process; } catch (Exception e) { throw new Exception($"dir: {Path.GetFullPath(workingDirectory)}, command: {exe} {arguments}", e); } } private static async ETTask WaitExitAsync(Process process) { await process.WaitForExitAsync(); #if UNITY Log.Info($"process exit, exitcode: {process.ExitCode} {process.StandardOutput.ReadToEnd()} {process.StandardError.ReadToEnd()}"); #endif } #if UNITY private static async Task WaitForExitAsync(this Process self) { if (!self.HasExited) { return; } try { self.EnableRaisingEvents = true; } catch (InvalidOperationException) { if (self.HasExited) { return; } throw; } var tcs = new TaskCompletionSource(); void Handler(object s, EventArgs e) => tcs.TrySetResult(true); self.Exited += Handler; try { if (self.HasExited) { return; } await tcs.Task; } finally { self.Exited -= Handler; } } #endif } }