// File: Services/ProcessMonitor.cs using Microsoft.Extensions.Options; using System.Runtime.Versioning; using WebmrAPI.Configuration; using WebmrAPI.Exceptions; using WebmrAPI.Models; using WebmrAPI.Services.Scanners; using WebmrAPI.Utils; namespace WebmrAPI.Services { [SupportedOSPlatform("windows")] public class ProcessMonitor : BackgroundService { private readonly ILogger _logger; private readonly MonitoringSettings _config; private LazyConcurrentContainer _processes = new(); private ScanProvider _provider; public ILogger Logger { get => _logger; } public MonitoringSettings Config { get => _config; } public LazyConcurrentContainer Processes { get => _processes; } public IEnumerable? GetBufferedProcesses() { return _processes.Values; } async public Task GetProcessDetails(int pid, ScanTarget target = ScanTarget.ProcessDetails) { if (_processes.Container != null && _processes.Container.TryGetValue(pid, out var info)) { try { await _provider.CreateScanTask(info, target).ScanAsync(); _logger.LogInformation($"Scan details of the process {info.Name} (PID: {info.PID}) was completed."); return info; } catch (ProcessMonitorException ex) { _logger.LogWarning(ex.Message); } catch (Exception ex) { _logger.LogError($"Unhandled error during scanning of the process {info.Name} (PID: {info.PID}): {ex.Message}"); } } return null; } public ProcessMonitor(ILogger logger, IOptions settings) { _logger = logger; _config = settings.Value.Monitoring; _provider = new(this); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation($"ProcessMonitor started. Scan interval: {_config.ProcessScanInterval} seconds."); await ScanAsync(); using var timer = new PeriodicTimer(TimeSpan.FromSeconds(_config.ProcessScanInterval)); try { while (await timer.WaitForNextTickAsync(stoppingToken)) { await ScanAsync(); } } catch (OperationCanceledException) { _logger.LogInformation("ProcessMonitor is stopping due to cancellation."); } catch (Exception ex) { _logger.LogError(ex, "ProcessMonitor encountered an unhandled exception and is stopping."); } } private async Task ScanAsync() { _logger.LogDebug("Initiating process scan..."); try { await _provider.CreateScanTask().ScanAsync(); _logger.LogInformation($"Process buffer updated, contains {Processes.Container?.Count} processes."); } catch (ProcessMonitorException ex) { _logger.LogWarning(ex.Message); } catch (Exception ex) { _logger.LogError($"Unhandled error during process monitoring cycle: {ex.Message}"); } } } }