823e467078
- Introduced a batch script to simplify the startup process for the Resource Monitor Service. - Included checks for .NET 9.0 Runtime installation. - Added build and run commands for the service with appropriate error handling. - Provided user instructions and API documentation links in the script output.
218 lines
8.5 KiB
C#
218 lines
8.5 KiB
C#
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<SystemInfo> GetSystemInfoAsync();
|
|
Task<bool> IsVirtualMachineAsync();
|
|
Task<string> GetHypervisorVendorAsync();
|
|
Task<DateTime> GetBootTimeAsync();
|
|
Task<string> GetCpuNameAsync();
|
|
}
|
|
|
|
public class SystemInfoService : ISystemInfoService
|
|
{
|
|
private readonly ILogger<SystemInfoService> _logger;
|
|
private readonly MonitoringSettings _settings;
|
|
private SystemInfo? _cachedSystemInfo;
|
|
private DateTime _lastCacheUpdate = DateTime.MinValue;
|
|
private readonly TimeSpan _cacheExpiration = TimeSpan.FromMinutes(5);
|
|
|
|
public SystemInfoService(ILogger<SystemInfoService> logger, IOptions<MonitoringSettings> settings)
|
|
{
|
|
_logger = logger;
|
|
_settings = settings.Value;
|
|
}
|
|
|
|
public async Task<SystemInfo> 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<bool> 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<string> 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<DateTime> 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<string> 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<ulong> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|