using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using ResourceMonitorService.Configuration; using ResourceMonitorService.Models; using System.Diagnostics; using System.Management; namespace ResourceMonitorService.Services { public interface ISystemInfoService { Task GetSystemInfoAsync(); Task IsVirtualMachineAsync(); Task GetHypervisorVendorAsync(); Task GetBootTimeAsync(); Task GetCpuNameAsync(); } public class SystemInfoService : ISystemInfoService { private readonly ILogger _logger; private readonly MonitoringSettings _settings; private SystemInfo? _cachedSystemInfo; private DateTime _lastCacheUpdate = DateTime.MinValue; private readonly TimeSpan _cacheExpiration = TimeSpan.FromMinutes(5); public SystemInfoService(ILogger logger, IOptions settings) { _logger = logger; _settings = settings.Value; } public async Task GetSystemInfoAsync() { if (_cachedSystemInfo != null && DateTime.Now - _lastCacheUpdate < _cacheExpiration) { _cachedSystemInfo.Uptime = DateTime.Now - _cachedSystemInfo.BootTime; return _cachedSystemInfo; } try { var systemInfo = new SystemInfo { MachineName = Environment.MachineName, OSVersion = System.Runtime.InteropServices.RuntimeInformation.OSDescription, OSArchitecture = System.Runtime.InteropServices.RuntimeInformation.OSArchitecture.ToString(), ProcessorCount = Environment.ProcessorCount, TotalPhysicalMemory = await GetTotalPhysicalMemoryAsync(), CPUName = await GetCpuNameAsync(), BootTime = await GetBootTimeAsync(), Domain = Environment.UserDomainName, IsVirtualMachine = await IsVirtualMachineAsync(), HypervisorVendor = await GetHypervisorVendorAsync() }; systemInfo.Uptime = DateTime.Now - systemInfo.BootTime; _cachedSystemInfo = systemInfo; _lastCacheUpdate = DateTime.Now; return systemInfo; } catch (Exception ex) { _logger.LogError(ex, "Error getting system information"); throw; } } public async Task IsVirtualMachineAsync() { try { return await Task.Run(() => { // Check for common VM indicators var queries = new[] { "SELECT * FROM Win32_ComputerSystem WHERE Manufacturer LIKE '%VMware%' OR Manufacturer LIKE '%VirtualBox%' OR Manufacturer LIKE '%Microsoft Corporation%' OR Model LIKE '%Virtual%'", "SELECT * FROM Win32_BIOS WHERE SerialNumber LIKE '%VMware%' OR SerialNumber LIKE '%VirtualBox%' OR Version LIKE '%VBOX%'", "SELECT * FROM Win32_SystemEnclosure WHERE Manufacturer LIKE '%VMware%' OR Manufacturer LIKE '%VirtualBox%'" }; foreach (var query in queries) { #pragma warning disable CA1416 // Validate platform compatibility using var searcher = new ManagementObjectSearcher(query); using var collection = searcher.Get(); if (collection.Count > 0) return true; #pragma warning restore CA1416 // Validate platform compatibility } return false; }); } catch (Exception ex) { _logger.LogWarning(ex, "Could not determine if running in virtual machine"); return false; } } public async Task GetHypervisorVendorAsync() { try { return await Task.Run(() => { #pragma warning disable CA1416 // Validate platform compatibility using var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem"); using var collection = searcher.Get(); foreach (ManagementObject obj in collection) { var manufacturer = obj["Manufacturer"]?.ToString() ?? ""; var model = obj["Model"]?.ToString() ?? ""; if (manufacturer.Contains("VMware")) return "VMware"; if (manufacturer.Contains("Microsoft Corporation") && model.Contains("Virtual")) return "Hyper-V"; if (manufacturer.Contains("QEMU")) return "QEMU/KVM"; if (manufacturer.Contains("VirtualBox")) return "VirtualBox"; if (manufacturer.Contains("Xen")) return "Xen"; } #pragma warning restore CA1416 // Validate platform compatibility return "Unknown"; }); } catch (Exception ex) { _logger.LogWarning(ex, "Could not determine hypervisor vendor"); return "Unknown"; } } public async Task GetBootTimeAsync() { try { return await Task.Run(() => { #pragma warning disable CA1416 // Validate platform compatibility using var searcher = new ManagementObjectSearcher("SELECT LastBootUpTime FROM Win32_OperatingSystem"); using var collection = searcher.Get(); foreach (ManagementObject obj in collection) { var bootTime = obj["LastBootUpTime"]?.ToString(); if (!string.IsNullOrEmpty(bootTime)) { return ManagementDateTimeConverter.ToDateTime(bootTime); } } #pragma warning restore CA1416 // Validate platform compatibility return DateTime.Now.AddMilliseconds(-Environment.TickCount64); }); } catch (Exception ex) { _logger.LogWarning(ex, "Could not get boot time from WMI, using tick count"); return DateTime.Now.AddMilliseconds(-Environment.TickCount64); } } public async Task GetCpuNameAsync() { try { return await Task.Run(() => { #pragma warning disable CA1416 // Validate platform compatibility using var searcher = new ManagementObjectSearcher("SELECT Name FROM Win32_Processor"); using var collection = searcher.Get(); foreach (ManagementObject obj in collection) { return obj["Name"]?.ToString()?.Trim() ?? "Unknown CPU"; } #pragma warning restore CA1416 // Validate platform compatibility return "Unknown CPU"; }); } catch (Exception ex) { _logger.LogWarning(ex, "Could not get CPU name"); return "Unknown CPU"; } } private async Task GetTotalPhysicalMemoryAsync() { try { return await Task.Run(() => { #pragma warning disable CA1416 // Validate platform compatibility using var searcher = new ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem"); using var collection = searcher.Get(); foreach (ManagementObject obj in collection) { return (ulong)obj["TotalPhysicalMemory"]; } #pragma warning restore CA1416 // Validate platform compatibility return (ulong)0; }); } catch (Exception ex) { _logger.LogWarning(ex, "Could not get total physical memory"); return 0; } } } }