From 5e652bcd59165b41b8078067c215ec72ab7833f7 Mon Sep 17 00:00:00 2001 From: "waffle.lord" Date: Wed, 22 Nov 2023 09:32:18 -0500 Subject: [PATCH] implement async read for net6 process --- SPTInstaller/Helpers/ProcessHelper.cs | 58 +++++++++++++++++++ .../PreChecks/NetCore6PreCheck.cs | 16 +++-- SPTInstaller/Models/ReadProcessResult.cs | 18 ++++++ SPTInstaller/SPTInstaller.csproj | 4 +- 4 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 SPTInstaller/Models/ReadProcessResult.cs diff --git a/SPTInstaller/Helpers/ProcessHelper.cs b/SPTInstaller/Helpers/ProcessHelper.cs index 63be9dc..9d8618e 100644 --- a/SPTInstaller/Helpers/ProcessHelper.cs +++ b/SPTInstaller/Helpers/ProcessHelper.cs @@ -1,4 +1,6 @@ using System.Diagnostics; +using System.Text; +using System.Threading; using SPTInstaller.Models; namespace SPTInstaller.Helpers; @@ -57,4 +59,60 @@ public static class ProcessHelper return Result.FromError("an unknown error occurred in the patcher"); } } + + public static ReadProcessResult RunAndReadProcessOutputs(string fileName, string args, int timeout = 5000) + { + using var proc = new Process(); + + proc.StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = args, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + }; + + var outputBuilder = new StringBuilder(); + var errorBuilder = new StringBuilder(); + + using AutoResetEvent outputWaitHandle = new AutoResetEvent(false); + using AutoResetEvent errorWaitHandle = new AutoResetEvent(false); + + proc.OutputDataReceived += (s, e) => + { + if (e.Data == null) + { + outputWaitHandle.Set(); + } + else + { + outputBuilder.AppendLine(e.Data); + } + }; + + proc.ErrorDataReceived += (s, e) => + { + if (e.Data == null) + { + errorWaitHandle.Set(); + } + else + { + errorBuilder.AppendLine(e.Data); + } + }; + + proc.Start(); + + proc.BeginOutputReadLine(); + proc.BeginErrorReadLine(); + + if (!proc.WaitForExit(timeout) || !outputWaitHandle.WaitOne(timeout) || !errorWaitHandle.WaitOne(timeout)) + { + return ReadProcessResult.FromError("Process timed out"); + } + + return ReadProcessResult.FromSuccess(outputBuilder.ToString(), errorBuilder.ToString()); + } } \ No newline at end of file diff --git a/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs b/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs index 851ca69..b9da03c 100644 --- a/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs +++ b/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs @@ -3,6 +3,7 @@ using SPTInstaller.Models; using System.Diagnostics; using System.Text.RegularExpressions; using System.Threading.Tasks; +using SPTInstaller.Helpers; namespace SPTInstaller.Installer_Tasks.PreChecks; @@ -32,17 +33,14 @@ public class NetCore6PreCheck : PreCheckBase try { - var proc = Process.Start(new ProcessStartInfo() + var result = ProcessHelper.RunAndReadProcessOutputs("dotnet", "--list-runtimes"); + + if (!result.Succeeded) { - FileName = "dotnet", - Arguments = "--list-runtimes", - RedirectStandardOutput = true, - CreateNoWindow = true - }); + return PreCheckResult.FromError(result.Message); + } - proc.WaitForExit(); - - output = proc.StandardOutput.ReadToEnd().Split("\r\n"); + output = result.StdOut.Split("\r\n"); } catch (Exception ex) { diff --git a/SPTInstaller/Models/ReadProcessResult.cs b/SPTInstaller/Models/ReadProcessResult.cs new file mode 100644 index 0000000..77e71ff --- /dev/null +++ b/SPTInstaller/Models/ReadProcessResult.cs @@ -0,0 +1,18 @@ +namespace SPTInstaller.Models; + +public class ReadProcessResult : Result +{ + public string StdOut { get; } + public string StdErr { get; } + + protected ReadProcessResult(string message, bool succeeded, string stdOut = "", string stdErr = "") : base(message, succeeded) + { + StdOut = stdOut; + StdErr = stdErr; + } + + public static ReadProcessResult FromSuccess(string stdOut, string stdErr) => + new ReadProcessResult("ok", true, stdOut, stdErr); + + public new static ReadProcessResult FromError(string message) => new ReadProcessResult(message, false); +} \ No newline at end of file diff --git a/SPTInstaller/SPTInstaller.csproj b/SPTInstaller/SPTInstaller.csproj index fc5c9a7..1d53b30 100644 --- a/SPTInstaller/SPTInstaller.csproj +++ b/SPTInstaller/SPTInstaller.csproj @@ -9,8 +9,8 @@ icon.ico Assets\icon.ico Debug;Release;TEST - 2.22.1 - 2.22.1 + 2.23 + 2.23 SPT-AKI