Files
TWA-App/TWASys-App/Models/ServerInfo/OsInfoReader.cs
2025-10-22 09:41:40 +07:00

129 lines
5.0 KiB
C#

using Microsoft.Win32;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace TWASys_App.Models.ServerInfo
{
public record OsInfo(string Platform, string Name, string Version, string Kernel, string Architecture);
public class OsInfoReader
{
public static OsInfo Get()
{
var arch = RuntimeInformation.OSArchitecture.ToString();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return GetWindows(arch);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return GetLinux(arch);
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return GetMac(arch);
return new OsInfo(RuntimeInformation.OSDescription, "Unknown", "Unknown", "Unknown", arch);
}
// ---------- Windows ----------
static OsInfo GetWindows(string arch)
{
string name = "Windows";
string version = "Unknown";
try
{
using var k = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
var productName = k?.GetValue("ProductName")?.ToString();
var displayVer = k?.GetValue("DisplayVersion")?.ToString() ?? k?.GetValue("ReleaseId")?.ToString();
var build = k?.GetValue("CurrentBuildNumber")?.ToString();
var ubrObj = k?.GetValue("UBR");
var ubr = ubrObj is int i ? i.ToString() : ubrObj?.ToString();
name = productName ?? "Windows";
if (!string.IsNullOrWhiteSpace(build))
version = $"{(displayVer ?? "")}".Trim();
if (!string.IsNullOrWhiteSpace(build))
version = string.IsNullOrWhiteSpace(version) ? $"Build {build}.{ubr}" : $"{version} (Build {build}.{ubr})";
}
catch { /* fallback below */ }
var kernel = RuntimeInformation.OSDescription; // e.g. "Microsoft Windows 10.0.19045"
return new OsInfo("Windows", name, version, kernel, arch);
}
// ---------- Linux ----------
static OsInfo GetLinux(string arch)
{
string name = "Linux";
string version = "Unknown";
try
{
var dict = ParseKeyValueFile("/etc/os-release"); // NAME, PRETTY_NAME, VERSION_ID...
if (dict.TryGetValue("NAME", out var n)) name = TrimQuotes(n);
if (dict.TryGetValue("PRETTY_NAME", out var pretty)) version = TrimQuotes(pretty);
else if (dict.TryGetValue("VERSION", out var v)) version = TrimQuotes(v);
else if (dict.TryGetValue("VERSION_ID", out var vid)) version = TrimQuotes(vid);
}
catch { /* ignore */ }
var kernel = Run("uname", "-sr"); // e.g. "Linux 6.8.0-40-generic"
if (string.IsNullOrWhiteSpace(kernel)) kernel = RuntimeInformation.OSDescription;
return new OsInfo("Linux", name, version, kernel, arch);
}
// ---------- macOS ----------
static OsInfo GetMac(string arch)
{
var name = Run("sw_vers", "-productName"); // "macOS"
var version = Run("sw_vers", "-productVersion"); // "14.6.1"
if (string.IsNullOrWhiteSpace(name)) name = "macOS";
if (string.IsNullOrWhiteSpace(version)) version = "Unknown";
var kernel = Run("uname", "-sr"); // "Darwin 23.6.0"
if (string.IsNullOrWhiteSpace(kernel)) kernel = RuntimeInformation.OSDescription;
return new OsInfo("macOS", name.Trim(), version.Trim(), kernel.Trim(), arch);
}
// ---------- helpers ----------
static Dictionary<string, string> ParseKeyValueFile(string path)
{
var d = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (!File.Exists(path)) return d;
foreach (var raw in File.ReadAllLines(path))
{
var line = raw.Trim();
if (line.Length == 0 || line.StartsWith("#")) continue;
var i = line.IndexOf('=');
if (i <= 0) continue;
d[line[..i]] = line[(i + 1)..];
}
return d;
}
static string TrimQuotes(string s) => s.Trim().Trim('"');
static string Run(string file, string args)
{
try
{
var p = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = file,
Arguments = args,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
}
};
p.Start();
var s = p.StandardOutput.ReadToEnd().Trim();
p.WaitForExit(1500);
return s;
}
catch { return ""; }
}
}
}