using Microsoft.Extensions.Logging; using Microsoft.Win32; using PatchProbe.Shared.Contracts; using PatchProbe.Shared.Models; namespace PatchProbe.Cli.Collectors; public sealed class OsCollector(ILogger logger) : ICollector { private const string CurrentVersionKey = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion"; public Task CollectAsync(CancellationToken cancellationToken = default) { logger.LogInformation("Collecting OS information"); using var key = Registry.LocalMachine.OpenSubKey(CurrentVersionKey); var installDateRaw = key?.GetValue("InstallDate"); DateTimeOffset? installDate = installDateRaw is int installDateInt ? DateTimeOffset.FromUnixTimeSeconds(installDateInt) : null; var info = new OsInfo { ProductName = key?.GetValue("ProductName")?.ToString(), EditionId = key?.GetValue("EditionID")?.ToString(), DisplayVersion = key?.GetValue("DisplayVersion")?.ToString(), ReleaseId = key?.GetValue("ReleaseId")?.ToString(), BuildNumber = key?.GetValue("CurrentBuildNumber")?.ToString(), Ubr = key?.GetValue("UBR") is int ubr ? ubr : 0, Architecture = Environment.Is64BitOperatingSystem ? "x64" : "x86", InstallDate = installDate, LastBoot = GetLastBoot(), }; return Task.FromResult(info); } private static DateTimeOffset? GetLastBoot() { try { var uptime = TimeSpan.FromMilliseconds(Environment.TickCount64); return DateTimeOffset.UtcNow - uptime; } catch { return null; } } }