using System.Diagnostics; using System.Runtime.InteropServices; #if WINDOWS using System.Management; // NuGet: System.Management #endif namespace TWASys_App.Models.ServerInfo { public record MachineHwIds(string? SerialNumber, string? BiosVendor, string? ProductUuid); public static class HwIdReader { public static MachineHwIds Get() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { #if WINDOWS string? serial = null, biosVendor = null, uuid = null; try { using var cs = new ManagementObjectSearcher( "SELECT UUID, IdentifyingNumber FROM Win32_ComputerSystemProduct"); foreach (ManagementObject mo in cs.Get()) { uuid = mo["UUID"]?.ToString(); serial = mo["IdentifyingNumber"]?.ToString(); // system serial break; } } catch { /* ignore */ } try { using var bios = new ManagementObjectSearcher( "SELECT Manufacturer FROM Win32_BIOS"); foreach (ManagementObject mo in bios.Get()) { biosVendor = mo["Manufacturer"]?.ToString(); break; } } catch { /* ignore */ } return new MachineHwIds(Null(serial), Null(biosVendor), Null(uuid)); #else return new MachineHwIds(null, null, null); #endif } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { string R(string p) => File.Exists(p) ? File.ReadAllText(p).Trim() : ""; var serial = R("/sys/class/dmi/id/product_serial"); var vendor = R("/sys/class/dmi/id/bios_vendor"); var uuid = R("/sys/class/dmi/id/product_uuid"); // Fallback (nếu sysfs rỗng và bạn cho phép): dmidecode (có thể cần sudo) if (string.IsNullOrWhiteSpace(serial)) serial = Exec("dmidecode", "-s system-serial-number"); if (string.IsNullOrWhiteSpace(vendor)) vendor = Exec("dmidecode", "-s bios-vendor"); if (string.IsNullOrWhiteSpace(uuid)) uuid = Exec("dmidecode", "-s system-uuid"); return new MachineHwIds(Null(serial), Null(vendor), Null(uuid)); } // macOS không có “BIOS”; có thể lấy serial máy nhưng BIOS vendor/UUID không tương đương return new MachineHwIds(null, null, null); } static string? Null(string s) => string.IsNullOrWhiteSpace(s) ? null : s; static string Exec(string file, string args) { try { var p = new Process { StartInfo = new ProcessStartInfo { FileName = file, Arguments = args, RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true } }; p.Start(); var s = p.StandardOutput.ReadToEnd().Trim(); p.WaitForExit(2000); return s; } catch { return ""; } } } }