implement async read for net6 process

This commit is contained in:
IsWaffle 2023-11-22 09:32:18 -05:00
parent 44010e91df
commit 5e652bcd59
4 changed files with 85 additions and 11 deletions

View File

@ -1,4 +1,6 @@
using System.Diagnostics; using System.Diagnostics;
using System.Text;
using System.Threading;
using SPTInstaller.Models; using SPTInstaller.Models;
namespace SPTInstaller.Helpers; namespace SPTInstaller.Helpers;
@ -57,4 +59,60 @@ public static class ProcessHelper
return Result.FromError("an unknown error occurred in the patcher"); 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());
}
} }

View File

@ -3,6 +3,7 @@ using SPTInstaller.Models;
using System.Diagnostics; using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using SPTInstaller.Helpers;
namespace SPTInstaller.Installer_Tasks.PreChecks; namespace SPTInstaller.Installer_Tasks.PreChecks;
@ -32,17 +33,14 @@ public class NetCore6PreCheck : PreCheckBase
try try
{ {
var proc = Process.Start(new ProcessStartInfo() var result = ProcessHelper.RunAndReadProcessOutputs("dotnet", "--list-runtimes");
if (!result.Succeeded)
{ {
FileName = "dotnet", return PreCheckResult.FromError(result.Message);
Arguments = "--list-runtimes", }
RedirectStandardOutput = true,
CreateNoWindow = true
});
proc.WaitForExit(); output = result.StdOut.Split("\r\n");
output = proc.StandardOutput.ReadToEnd().Split("\r\n");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -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);
}

View File

@ -9,8 +9,8 @@
<PackageIcon>icon.ico</PackageIcon> <PackageIcon>icon.ico</PackageIcon>
<ApplicationIcon>Assets\icon.ico</ApplicationIcon> <ApplicationIcon>Assets\icon.ico</ApplicationIcon>
<Configurations>Debug;Release;TEST</Configurations> <Configurations>Debug;Release;TEST</Configurations>
<AssemblyVersion>2.22.1</AssemblyVersion> <AssemblyVersion>2.23</AssemblyVersion>
<FileVersion>2.22.1</FileVersion> <FileVersion>2.23</FileVersion>
<Company>SPT-AKI</Company> <Company>SPT-AKI</Company>
</PropertyGroup> </PropertyGroup>