using Microsoft.Extensions.Logging; using Microsoft.Win32; using RmmAgent.Models; using System.Management; namespace RmmAgent.Services; #pragma warning disable CA1416 public class InventoryCollector { private readonly ILogger _logger; public InventoryCollector(ILogger logger) { _logger = logger; } public SystemInfo CollectBasic() { string osName = "", osVersion = "", osBuild = "", cpuModel = ""; int ramTotalMb = 0; try { using var os = new ManagementObjectSearcher("SELECT Caption, Version, BuildNumber FROM Win32_OperatingSystem"); foreach (var o in os.Get()) { osName = o["Caption"]?.ToString() ?? ""; osVersion = o["Version"]?.ToString() ?? ""; osBuild = o["BuildNumber"]?.ToString() ?? ""; break; } } catch (Exception ex) { _logger.LogWarning(ex, "OS info failed"); } try { using var cpu = new ManagementObjectSearcher("SELECT Name FROM Win32_Processor"); foreach (var c in cpu.Get()) { cpuModel = c["Name"]?.ToString()?.Trim() ?? ""; break; } } catch (Exception ex) { _logger.LogWarning(ex, "CPU info failed"); } try { using var mem = new ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem"); foreach (var m in mem.Get()) { ramTotalMb = (int)(Convert.ToInt64(m["TotalPhysicalMemory"]) / (1024 * 1024)); break; } } catch (Exception ex) { _logger.LogWarning(ex, "RAM info failed"); } return new SystemInfo(osName, osVersion, osBuild, cpuModel, ramTotalMb); } public InventoryRequest Collect() { return new InventoryRequest( Hardware: CollectHardware(), Software: CollectSoftware(), Services: CollectServices(), Users: CollectUsers(), Security: CollectSecurity()); } private object CollectHardware() { var data = new Dictionary(); try { using var sys = new ManagementObjectSearcher("SELECT Manufacturer, Model, TotalPhysicalMemory FROM Win32_ComputerSystem"); foreach (var s in sys.Get()) { data["manufacturer"] = s["Manufacturer"]?.ToString(); data["model"] = s["Model"]?.ToString(); data["totalRamMb"] = Convert.ToInt64(s["TotalPhysicalMemory"]) / (1024 * 1024); break; } } catch { } try { using var bios = new ManagementObjectSearcher("SELECT Manufacturer, SerialNumber, SMBIOSBIOSVersion FROM Win32_BIOS"); foreach (var b in bios.Get()) { data["biosVendor"] = b["Manufacturer"]?.ToString(); data["biosVersion"] = b["SMBIOSBIOSVersion"]?.ToString(); data["serialNumber"] = b["SerialNumber"]?.ToString(); break; } } catch { } try { var cpus = new List(); using var cpu = new ManagementObjectSearcher("SELECT Name, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed FROM Win32_Processor"); foreach (var c in cpu.Get()) cpus.Add(new { name = c["Name"]?.ToString()?.Trim(), cores = c["NumberOfCores"], threads = c["NumberOfLogicalProcessors"], maxClockMhz = c["MaxClockSpeed"] }); data["cpus"] = cpus; } catch { } try { var disks = new List(); foreach (var drive in DriveInfo.GetDrives()) { if (!drive.IsReady) continue; disks.Add(new { name = drive.Name, label = drive.VolumeLabel, fileSystem = drive.DriveFormat, type = drive.DriveType.ToString(), totalGb = Math.Round(drive.TotalSize / 1e9, 2), freeGb = Math.Round(drive.AvailableFreeSpace / 1e9, 2) }); } data["disks"] = disks; } catch { } try { var nics = new List(); using var net = new ManagementObjectSearcher("SELECT Description, MACAddress, IPAddress FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE"); foreach (var n in net.Get()) nics.Add(new { description = n["Description"]?.ToString(), mac = n["MACAddress"]?.ToString(), ipAddresses = n["IPAddress"] as string[] }); data["network"] = nics; } catch { } try { var gpus = new List(); using var gpu = new ManagementObjectSearcher("SELECT Name, AdapterRAM, DriverVersion FROM Win32_VideoController"); foreach (var g in gpu.Get()) gpus.Add(new { name = g["Name"]?.ToString(), vramMb = g["AdapterRAM"] != null ? Convert.ToInt64(g["AdapterRAM"]) / (1024 * 1024) : 0, driver = g["DriverVersion"]?.ToString() }); data["gpus"] = gpus; } catch { } return data; } private object CollectSoftware() { var apps = new List(); var keys = new[] { @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", }; foreach (var keyPath in keys) { try { using var key = Registry.LocalMachine.OpenSubKey(keyPath); if (key is null) continue; foreach (var subName in key.GetSubKeyNames()) { using var sub = key.OpenSubKey(subName); if (sub is null) continue; var name = sub.GetValue("DisplayName") as string; if (string.IsNullOrWhiteSpace(name)) continue; var sc = sub.GetValue("SystemComponent"); if (sc is int v && v == 1) continue; apps.Add(new { name, version = sub.GetValue("DisplayVersion") as string, publisher = sub.GetValue("Publisher") as string, installDate = sub.GetValue("InstallDate") as string }); } } catch (Exception ex) { _logger.LogDebug(ex, "Registry walk failed"); } } return new { count = apps.Count, items = apps }; } private object CollectServices() { var services = new List(); try { using var s = new ManagementObjectSearcher("SELECT Name, DisplayName, State, StartMode FROM Win32_Service"); foreach (var svc in s.Get()) services.Add(new { name = svc["Name"]?.ToString(), displayName = svc["DisplayName"]?.ToString(), state = svc["State"]?.ToString(), startMode = svc["StartMode"]?.ToString() }); } catch (Exception ex) { _logger.LogWarning(ex, "Services collect failed"); } return new { count = services.Count, items = services }; } private object CollectUsers() { var users = new List(); try { using var u = new ManagementObjectSearcher("SELECT Name, FullName, Disabled FROM Win32_UserAccount WHERE LocalAccount = TRUE"); foreach (var user in u.Get()) users.Add(new { name = user["Name"]?.ToString(), fullName = user["FullName"]?.ToString(), disabled = user["Disabled"] }); } catch (Exception ex) { _logger.LogWarning(ex, "Users collect failed"); } return new { items = users }; } private object CollectSecurity() { var sec = new Dictionary(); try { using var av = new ManagementObjectSearcher(@"\\.\root\SecurityCenter2", "SELECT displayName, productState FROM AntiVirusProduct"); foreach (var p in av.Get()) { sec["antivirus"] = new { product = p["displayName"]?.ToString(), state = p["productState"] }; break; } } catch { sec["antivirus"] = null; } try { using var bl = new ManagementObjectSearcher(@"\\.\root\CIMv2\Security\MicrosoftVolumeEncryption", "SELECT * FROM Win32_EncryptableVolume"); int encrypted = 0, total = 0; foreach (var v in bl.Get()) { total++; if (v["ProtectionStatus"] is int s && s == 1) encrypted++; } sec["bitlocker"] = new { enabled = encrypted > 0, encryptedVolumes = encrypted, totalVolumes = total }; } catch { sec["bitlocker"] = new { enabled = false }; } try { using var fw = new ManagementObjectSearcher(@"\\.\root\StandardCimv2", "SELECT * FROM MSFT_NetFirewallProfile"); bool anyEnabled = false; foreach (var p in fw.Get()) { if (p["Enabled"] is ushort u && u == 1) { anyEnabled = true; break; } if (p["Enabled"] is bool b && b) { anyEnabled = true; break; } } sec["firewall"] = new { enabled = anyEnabled }; } catch { sec["firewall"] = new { enabled = false }; } return sec; } }