using System.Runtime.InteropServices; using Monitor.Protocol; namespace Monitor.Measurement; /// /// 读出本机的系统名和架构,只用于在面板上展示。故意只取粗粒度的信息: /// 「Debian 12」「Windows 11」「x64」,不读主机名、内核版本、CPU 型号。 /// public static class PlatformDetector { public static PlatformInfo Detect() { PlatformInfo info = Detect(File.Exists("/etc/os-release") ? File.ReadAllLines("/etc/os-release") : []); info.Version = Empty(BuildInfo.Version); info.Tag = Empty(BuildInfo.Tag); info.Commit = Empty(BuildInfo.Commit); info.BuiltAt = Empty(BuildInfo.BuiltAt); return info; } private static string? Empty(string value) => value.Length == 0 ? null : value; /// `osRelease` 是 /etc/os-release 的各行(Linux 之外不用)。拆出来是为了好测。 internal static PlatformInfo Detect(IEnumerable osRelease) { string arch = RuntimeInformation.OSArchitecture switch { Architecture.X64 => "x64", Architecture.Arm64 => "arm64", Architecture.Arm => "arm", Architecture.X86 => "x86", var other => other.ToString().ToLowerInvariant(), }; if (OperatingSystem.IsWindows()) { // Windows 11 的版本号还是 10.0,靠内部版本号(22000 起)区分 string name = Environment.OSVersion.Version.Build >= 22000 ? "Windows 11" : "Windows 10"; return new PlatformInfo { Os = "windows", Name = name, Arch = arch }; } if (OperatingSystem.IsMacOS()) { return new PlatformInfo { Os = "macos", Name = "macOS", Arch = arch }; } if (OperatingSystem.IsLinux()) { return new PlatformInfo { Os = "linux", Name = LinuxName(osRelease), Arch = arch }; } return new PlatformInfo { Os = "other", Name = null, Arch = arch }; } /// 从 os-release 里取发行版名字和主版本:「Debian GNU/Linux 12 (bookworm)」→「Debian 12」,「OpenWrt 24.10.0」→「OpenWrt 24.10」。 internal static string LinuxName(IEnumerable osRelease) { var values = new Dictionary(StringComparer.Ordinal); foreach (string line in osRelease) { int eq = line.IndexOf('=', StringComparison.Ordinal); if (eq > 0) { values[line[..eq].Trim()] = line[(eq + 1)..].Trim().Trim('"', '\''); } } string name = values.GetValueOrDefault("NAME") ?? values.GetValueOrDefault("ID") ?? "Linux"; name = name.Replace(" GNU/Linux", string.Empty, StringComparison.Ordinal).Trim(); string? version = values.GetValueOrDefault("VERSION_ID"); if (string.IsNullOrEmpty(version)) { return name; } // 只留 主.次:Alpine 的 3.22.1、OpenWrt 的 24.10.0 都截成两段;Debian 的 12 本来就一段 string[] parts = version.Split('.'); return $"{name} {string.Join('.', parts.Take(2))}"; } }