VeraCrypt loader to be async
Opened this issue · 0 comments
DamianSuess commented
As a user, I want the ProcessStart execution to be async.
This would assist the VeraCrypt driver loader in VeraCrypt/Drive.cs
and VeraCryptAddin/Domain/VirtualDrive.cs
.
Sample Start Process Async
Reference: RoslynPad
Usage
var buildArgs =
$"-nologo -v:q -p:Configuration={optimizationLevel} -p:AssemblyName={Name} " +
$"-bl:ProjectImports=None \"{csprojPath}\" ";
using var buildResult = await ProcessUtil.RunProcessAsync(
DotNetExecutable,
BuildPath,
$"build {buildArgs}",
cancellationToken).ConfigureAwait(false);
await buildResult.WaitForExitAsync().ConfigureAwait(false);
ProcessUtil
internal class ProcessUtil
{
public static async Task<ProcessResult> RunProcessAsync(string path, string workingDirectory, string arguments, CancellationToken cancellationToken)
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = path,
WorkingDirectory = workingDirectory,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
UseShellExecute = false,
},
EnableRaisingEvents = true,
};
var exitTcs = new TaskCompletionSource<object?>();
process.Exited += (_, _) => exitTcs.TrySetResult(null);
using var _ = cancellationToken.Register(() =>
{
try
{
exitTcs.TrySetCanceled();
process.Kill();
}
catch { }
});
await Task.Run(process.Start).ConfigureAwait(false);
return new ProcessResult(process, exitTcs);
}
public class ProcessResult : IDisposable
{
private readonly Process _process;
private readonly TaskCompletionSource<object?> _exitTcs;
private readonly StringBuilder _standardOutput;
internal ProcessResult(Process process, TaskCompletionSource<object?> exitTcs)
{
_process = process;
_exitTcs = exitTcs;
_standardOutput = new StringBuilder();
_ = Task.Run(ReadStandardErrorAsync);
}
private async Task ReadStandardErrorAsync() =>
StandardError = await _process.StandardError.ReadToEndAsync().ConfigureAwait(false);
public Task WaitForExitAsync() => _exitTcs.Task;
public async IAsyncEnumerable<string> GetStandardOutputLinesAsync()
{
var output = _process.StandardOutput;
while (true)
{
var line = await output.ReadLineAsync().ConfigureAwait(false);
if (line == null)
{
await _exitTcs.Task.ConfigureAwait(false);
yield break;
}
if (!string.IsNullOrWhiteSpace(line))
{
_standardOutput.AppendLine(line);
yield return line;
}
}
}
public int ExitCode => _process.ExitCode;
public string StandardOutput => _standardOutput.ToString();
public string? StandardError { get; private set; }
public void Dispose() => _process.Dispose();
}
}