using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; using Inventory.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace Inventory.Agent { public class Worker : BackgroundService { private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; private readonly IHostApplicationLifetime _hostApplicationLifetime; public Worker(ILogger logger, IServiceProvider serviceProvider, IHostApplicationLifetime hostApplicationLifetime) { _logger = logger; _serviceProvider = serviceProvider; _hostApplicationLifetime = hostApplicationLifetime; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("Checking for agent updates..."); const string manifestPath = @"\\192.168.0.9\ihomp\InventoryAgent\Agent\version.json"; if (UpdateChecker.CheckForUpdate(manifestPath, out string newMsiPath)) { _logger.LogInformation("New version found. Starting silent update from {Path}", newMsiPath); try { // Copy MSI locally to avoid file lock on the share string tempMsi = Path.Combine(Path.GetTempPath(), Path.GetFileName(newMsiPath)); File.Copy(newMsiPath, tempMsi, true); Process.Start(new ProcessStartInfo { FileName = "msiexec.exe", Arguments = $"/i \"{tempMsi}\" /quiet /norestart", UseShellExecute = true, Verb = "runas" }); _logger.LogInformation("Update process started. Stopping current service..."); _hostApplicationLifetime.StopApplication(); return; } catch (Exception ex) { _logger.LogError(ex, "Failed to start update process."); } } _logger.LogInformation("Agent is up-to-date."); _logger.LogInformation("Inventory Agent starting."); // Perform an initial run on startup await DoWork(stoppingToken); var updateIntervalMinutes = Core.Secrets.UpdateIntervalMinutes; _logger.LogInformation("Update interval set to {Minutes} minutes.", updateIntervalMinutes); using var timer = new PeriodicTimer(TimeSpan.FromMinutes(updateIntervalMinutes)); while (await timer.WaitForNextTickAsync(stoppingToken)) { await DoWork(stoppingToken); } } private async Task DoWork(CancellationToken stoppingToken) { _logger.LogInformation("Starting inventory update workflow."); try { using var scope = _serviceProvider.CreateScope(); var updateWorkflow = scope.ServiceProvider.GetRequiredService(); await updateWorkflow.Run(); _logger.LogInformation("Inventory update completed successfully."); } catch (Exception ex) { _logger.LogError(ex, "An error occurred during the inventory update."); } } } }