using Microsoft.Extensions.Logging; using Microsoft.Win32; using PatchProbe.Shared.Contracts; using PatchProbe.Shared.Models; namespace PatchProbe.Cli.Collectors; public sealed class WindowsUpdatePolicyCollector(ILogger logger) : ICollector { private const string WuPolicyKey = @"SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; private const string AuPolicyKey = @"SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"; private const string WuUxKey = @"SOFTWARE\Microsoft\WindowsUpdate\UX\Settings"; public Task CollectAsync(CancellationToken cancellationToken = default) { logger.LogInformation("Collecting Windows Update policy"); using var wuKey = Registry.LocalMachine.OpenSubKey(WuPolicyKey); using var auKey = Registry.LocalMachine.OpenSubKey(AuPolicyKey); using var uxKey = Registry.LocalMachine.OpenSubKey(WuUxKey); var wsusServer = wuKey?.GetValue("WUServer")?.ToString(); var policy = new WindowsUpdatePolicy { WsusConfigured = !string.IsNullOrEmpty(wsusServer), WsusServer = wsusServer, WsusStatusServer = wuKey?.GetValue("WUStatusServer")?.ToString(), WufbConfigured = wuKey?.GetValue("ManagePreviewBuilds") != null || uxKey?.GetValue("BranchReadinessLevel") != null, DeferFeatureUpdatesDays = GetInt(wuKey, "DeferFeatureUpdatesPeriodInDays") ?? GetInt(uxKey, "DeferFeatureUpdatesPeriodInDays"), DeferQualityUpdatesDays = GetInt(wuKey, "DeferQualityUpdatesPeriodInDays") ?? GetInt(uxKey, "DeferQualityUpdatesPeriodInDays"), AutoUpdateEnabled = GetInt(auKey, "NoAutoUpdate") != 1, AuOptions = GetInt(auKey, "AUOptions"), TargetGroupEnabled = GetInt(wuKey, "TargetGroupEnabled") == 1, TargetGroup = wuKey?.GetValue("TargetGroup")?.ToString(), BranchReadinessLevel = uxKey?.GetValue("BranchReadinessLevel")?.ToString(), }; return Task.FromResult(policy); } private static int? GetInt(RegistryKey? key, string name) { if (key?.GetValue(name) is int v) return v; return null; } }