using System.Diagnostics; namespace Lumi.Companion.PluginHost; public sealed class PluginWorker(string executable, string arguments) : IAsyncDisposable { private Process? _process; public void Start() { if (_process is { HasExited: false }) return; _process = Process.Start(new ProcessStartInfo(executable, arguments) { UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardOutput = true }) ?? throw new InvalidOperationException("Companion plugin worker could not start."); } public bool Healthy => _process is { HasExited: false }; public async ValueTask DisposeAsync() { if (_process is not { HasExited: false }) return; _process.CloseMainWindow(); using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(2)); try { await _process.WaitForExitAsync(timeout.Token); } catch (OperationCanceledException) { _process.Kill(entireProcessTree: true); } _process.Dispose(); } }