InventoryAgent/Inventory.Core/SystemInfoCollector.cs
2025-10-20 00:03:49 +08:00

421 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.DirectoryServices.AccountManagement;
using System.Text.Json;
namespace Inventory.Core
{
public class SystemInfoCollector
{
public string GetComputerName()
{
return Environment.MachineName;
}
public string GetDeviceType()
{
if (!OperatingSystem.IsWindows()) return "N/A";
// Using Win32_SystemEnclosure to determine device type
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_SystemEnclosure");
foreach (ManagementObject mo in searcher.Get())
{
foreach (int chassisType in (ushort[])mo["ChassisTypes"])
{
switch (chassisType)
{
case 3: // Desktop
case 4: // Low Profile Desktop
case 5: // Pizza Box
case 6: // Mini Tower
case 7: // Tower
return "Desktop";
case 8: // Portable
case 9: // Laptop
case 10: // Notebook
case 11: // Hand Held
case 12: // Docking Station
case 14: // Sub Notebook
return "Laptop";
case 23: // Rack Mount Chassis
return "Server";
}
}
}
}
catch { /* Ignore WMI errors */ }
// Fallback to checking for a battery
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Battery");
if (searcher.Get().Count > 0)
{
return "Laptop";
}
}
catch { /* Ignore WMI errors */ }
return "Unknown";
}
public string? GetSystemSerialNumber()
{
if (!OperatingSystem.IsWindows()) return "N/A";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BIOS");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
return mo?["SerialNumber"]?.ToString()?.Trim();
}
catch { return "N/A"; }
}
public string? GetMotherboardSerialNumber()
{
if (!OperatingSystem.IsWindows()) return "N/A";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
return mo?["SerialNumber"]?.ToString()?.Trim();
}
catch { return "N/A"; }
}
public string? GetSystemUUID()
{
if (!OperatingSystem.IsWindows()) return "N/A";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
return mo?["UUID"]?.ToString()?.Trim();
}
catch { return "N/A"; }
}
public string? GetProcessor()
{
if (!OperatingSystem.IsWindows()) return "N/A";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Name FROM Win32_Processor");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
return mo?["Name"]?.ToString()?.Trim();
}
catch { return "N/A"; }
}
public string GetTotalRAM()
{
if (!OperatingSystem.IsWindows()) return "N/A";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
if (mo != null)
{
ulong ramBytes = (ulong)mo["TotalPhysicalMemory"];
double ramGB = Math.Round(ramBytes / (1024.0 * 1024.0 * 1024.0));
return $"{ramGB} GB";
}
return "N/A";
}
catch { return "N/A"; }
}
public List<string> GetGPUs()
{
var gpus = new List<string>();
if (!OperatingSystem.IsWindows()) return gpus;
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Name FROM Win32_VideoController");
foreach (ManagementObject mo in searcher.Get())
{
gpus.Add(mo["Name"]?.ToString()?.Trim() ?? "");
}
}
catch { /* Ignore WMI errors */ }
return gpus;
}
public List<StorageDeviceInfo> GetStorage()
{
var drives = new List<StorageDeviceInfo>();
if (!OperatingSystem.IsWindows()) return drives;
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"root\Microsoft\Windows\Storage", "SELECT * FROM MSFT_PhysicalDisk");
foreach (ManagementObject mo in searcher.Get())
{
string mediaType = "Unknown";
switch ((ushort)mo["MediaType"])
{
case 3: mediaType = "HDD"; break;
case 4: mediaType = "SSD"; break;
}
drives.Add(new StorageDeviceInfo
{
Model = mo["Model"]?.ToString()?.Trim(),
SerialNumber = mo["SerialNumber"]?.ToString()?.Trim(),
MediaType = mediaType,
InterfaceType = mo["BusType"]?.ToString()?.Trim(),
Size = (ulong)mo["Size"]
});
}
}
catch { /* Ignore WMI errors */ }
return drives;
}
public List<PrinterInfo> GetPrinters()
{
var printers = new List<PrinterInfo>();
if (!OperatingSystem.IsWindows()) return printers;
try
{
var ignoredPrinters = new List<string>
{
// Microsoft standard virtual printers
"Microsoft Print to PDF",
"Microsoft XPS Document Writer",
"OneNote", // Catches "OneNote for Windows 10" and "OneNote (Desktop)"
"Fax",
"Send to OneNote",
// Common 3rd-party PDF printers
"Adobe PDF",
"CutePDF",
"Bullzip",
"doPDF",
"Foxit",
"PrimoPDF",
"PDF Architect",
// Other virtual/utility printers
"Snagit",
"WebEx",
"AnyDesk"
};
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer");
foreach (ManagementObject mo in searcher.Get())
{
string? name = mo["Name"]?.ToString()?.Trim();
if (name != null && !ignoredPrinters.Any(p => name.Contains(p, StringComparison.OrdinalIgnoreCase)))
{
string? serialNumber = null;
string? pnpDeviceId = mo["PNPDeviceID"]?.ToString();
// Attempt to extract serial number from PNPDeviceID for USB printers
// Example ID: "USBPRINT\HEWLETT-PACKARDHP_LASERJET_PROFESSIONAL_M1212NF_MFP\7&1B442418&0&USB001"
// The last part after the model name is often a unique identifier or serial.
if (!string.IsNullOrEmpty(pnpDeviceId) && pnpDeviceId.Contains("USB"))
{
var parts = pnpDeviceId.Split('\\');
if (parts.Length > 2)
{
serialNumber = parts[2]; // This is often the most unique part available
}
}
printers.Add(new PrinterInfo
{
Name = name,
DriverName = mo["DriverName"]?.ToString()?.Trim(),
IsShared = (bool)mo["Shared"],
IsNetwork = (bool)mo["Network"],
HostName = mo["SystemName"]?.ToString()?.Trim(),
PortName = mo["PortName"]?.ToString()?.Trim(),
SerialNumber = serialNumber
});
}
}
}
catch { /* Ignore WMI errors */ }
return printers;
}
public bool HasOpticalDrive()
{
if (!OperatingSystem.IsWindows()) return false;
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_CDROMDrive");
return searcher.Get().Count > 0;
}
catch { return false; }
}
public List<MonitorInfo> GetMonitors()
{
var monitors = new List<MonitorInfo>();
if (!OperatingSystem.IsWindows()) return monitors;
try
{
// Get PnPDeviceID from Win32_DesktopMonitor
var pnpDeviceIds = new Dictionary<string, string>();
ManagementObjectSearcher desktopMonitorSearcher = new ManagementObjectSearcher("SELECT PNPDeviceID, Name FROM Win32_DesktopMonitor");
foreach (ManagementObject mo in desktopMonitorSearcher.Get())
{
pnpDeviceIds[mo["Name"]?.ToString() ?? string.Empty] = mo["PNPDeviceID"]?.ToString() ?? "Unknown";
}
// Get Serial and Model from WmiMonitorID
ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"root\wmi", "SELECT InstanceName, SerialNumberID, UserFriendlyName FROM WmiMonitorID");
foreach (ManagementObject mo in searcher.Get())
{
string model = "Unknown";
string serial = "Unknown";
string instanceName = mo["InstanceName"]?.ToString()?.TrimEnd('_', '0') ?? string.Empty;
if (mo["UserFriendlyName"] is ushort[] modelName)
{
model = System.Text.Encoding.ASCII.GetString(modelName.Select(c => (byte)c).ToArray()).Trim('\0');
}
if (mo["SerialNumberID"] is ushort[] serialNumberID)
{
serial = System.Text.Encoding.ASCII.GetString(serialNumberID.Select(c => (byte)c).ToArray()).Trim('\0');
}
monitors.Add(new MonitorInfo
{
Model = model,
SerialNumber = serial,
PnPDeviceID = pnpDeviceIds.Values.FirstOrDefault(pnp => instanceName.Contains(pnp)) ?? "N/A"
});
}
}
catch { /* Ignore WMI errors */ }
return monitors;
}
public string? GetOSVersion()
{
if (!OperatingSystem.IsWindows()) return "N/A";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
return mo?["Caption"]?.ToString()?.Trim();
}
catch { return "N/A"; }
}
public DateTime? GetOSInstallDate()
{
if (!OperatingSystem.IsWindows()) return null;
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT InstallDate FROM Win32_OperatingSystem");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
var installDate = mo?["InstallDate"]?.ToString();
return installDate != null ? ManagementDateTimeConverter.ToDateTime(installDate) : null;
}
catch { return null; }
}
public string? GetOSLicenseKey()
{
if (!OperatingSystem.IsWindows()) return "N/A";
try
{
// This is a common method but may not work on all systems, especially with newer licensing methods.
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT OA3xOriginalProductKey FROM SoftwareLicensingService");
ManagementObject? mo = searcher.Get().OfType<ManagementObject>().FirstOrDefault();
return mo?["OA3xOriginalProductKey"]?.ToString()?.Trim();
}
catch { return "N/A"; }
}
public List<LocalAdminInfo> GetLocalAdmins()
{
var admins = new List<LocalAdminInfo>();
if (!OperatingSystem.IsWindows()) return admins;
try
{
using (var context = new PrincipalContext(ContextType.Machine))
{
var group = GroupPrincipal.FindByIdentity(context, "Administrators");
if (group != null)
{
// Perform a recursive search to find all members, including those in nested groups.
// Then, use DistinctBy to remove duplicates based on the unique SID.
#pragma warning disable CA1416 // Validate platform compatibility
var uniqueMembers = group.GetMembers(true).DistinctBy(p => p.Sid);
#pragma warning restore CA1416 // Validate platform compatibility
foreach (Principal principal in uniqueMembers)
{
var adminInfo = new LocalAdminInfo
{
Name = principal.Name,
Sid = principal.Sid.ToString(),
AccountType = principal is UserPrincipal ? "User" : "Group",
Source = principal.Context.ContextType == ContextType.Machine ? "Local" : "Domain"
};
if (principal is UserPrincipal user)
{
adminInfo.IsEnabled = user.Enabled;
adminInfo.IsLockedOut = user.IsAccountLockedOut();
}
admins.Add(adminInfo);
}
}
}
}
catch { /* Ignore errors, e.g. on non-domain machines */ }
return admins;
}
public (List<string> IPAddresses, string? MACAddress) GetNetworkInfo()
{
try
{
var allIps = new List<string>();
string? primaryMac = null;
var operationalNics = NetworkInterface.GetAllNetworkInterfaces()
.Where(ni => ni.OperationalStatus == OperationalStatus.Up &&
ni.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
ni.NetworkInterfaceType != NetworkInterfaceType.Tunnel)
.Select(ni => new
{
Interface = ni,
IPProps = ni.GetIPProperties()
})
.Where(x => !(x.Interface.Description.Contains("Virtual") || x.Interface.Name.Contains("Virtual")));
foreach (var nic in operationalNics)
{
allIps.AddRange(nic.IPProps.UnicastAddresses
.Where(ua => ua.Address.AddressFamily == AddressFamily.InterNetwork)
.Select(ua => ua.Address.ToString()));
}
// Find the primary MAC address from the interface with a gateway, ordered by speed
var primaryNic = operationalNics.Where(n => n.IPProps.GatewayAddresses.Any()).OrderByDescending(n => n.Interface.Speed).FirstOrDefault();
primaryMac = primaryNic?.Interface.GetPhysicalAddress().ToString();
return (allIps.Distinct().ToList(), primaryMac);
}
catch { /* Ignore errors */ }
return (new List<string>(), "N/A");
}
}
}