update news & events
This commit is contained in:
185
TWASys-App/Models/ServerInfo/SysInfoReader.cs
Normal file
185
TWASys-App/Models/ServerInfo/SysInfoReader.cs
Normal file
@ -0,0 +1,185 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
#if WINDOWS
|
||||
using System.Management; // NuGet: System.Management
|
||||
using Microsoft.Win32;
|
||||
#endif
|
||||
|
||||
namespace TWASys_App.Models.ServerInfo
|
||||
{
|
||||
public record SysInfo(int SocketCount, string? CpuName, ulong TotalRamBytes);
|
||||
|
||||
public static class SysInfoReader
|
||||
{
|
||||
public static SysInfo Get()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return GetWindows();
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return GetLinux();
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
return GetMac();
|
||||
return new SysInfo(0, null, 0);
|
||||
}
|
||||
|
||||
// ---------- Windows ----------
|
||||
static SysInfo GetWindows()
|
||||
{
|
||||
string? name = null;
|
||||
int sockets = 0;
|
||||
|
||||
#if WINDOWS
|
||||
// CPU name: registry
|
||||
try
|
||||
{
|
||||
using var k = Registry.LocalMachine.OpenSubKey(
|
||||
@"HARDWARE\DESCRIPTION\System\CentralProcessor\0");
|
||||
name = k?.GetValue("ProcessorNameString")?.ToString()?.Trim();
|
||||
} catch { }
|
||||
|
||||
// Sockets: mỗi Win32_Processor ~ 1 physical socket
|
||||
try
|
||||
{
|
||||
using var s = new ManagementObjectSearcher(
|
||||
"SELECT SocketDesignation FROM Win32_Processor");
|
||||
foreach (ManagementObject _ in s.Get()) sockets++;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fallback
|
||||
try
|
||||
{
|
||||
using var s2 = new ManagementObjectSearcher(
|
||||
"SELECT NumberOfProcessors FROM Win32_ComputerSystem");
|
||||
foreach (ManagementObject mo in s2.Get())
|
||||
sockets = Convert.ToInt32(mo["NumberOfProcessors"]);
|
||||
} catch { }
|
||||
}
|
||||
#endif
|
||||
// RAM: GlobalMemoryStatusEx
|
||||
ulong total = GetTotalRamWindows();
|
||||
return new SysInfo(sockets, name, total);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
struct MEMORYSTATUSEX
|
||||
{
|
||||
public uint dwLength;
|
||||
public uint dwMemoryLoad;
|
||||
public ulong ullTotalPhys;
|
||||
public ulong ullAvailPhys;
|
||||
public ulong ullTotalPageFile;
|
||||
public ulong ullAvailPageFile;
|
||||
public ulong ullTotalVirtual;
|
||||
public ulong ullAvailVirtual;
|
||||
public ulong ullAvailExtendedVirtual;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
|
||||
|
||||
static ulong GetTotalRamWindows()
|
||||
{
|
||||
var st = new MEMORYSTATUSEX { dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>() };
|
||||
return GlobalMemoryStatusEx(ref st) ? st.ullTotalPhys : 0UL;
|
||||
}
|
||||
|
||||
// ---------- Linux ----------
|
||||
static SysInfo GetLinux()
|
||||
{
|
||||
// CPU name
|
||||
string? name = null;
|
||||
try
|
||||
{
|
||||
foreach (var line in File.ReadLines("/proc/cpuinfo"))
|
||||
if (line.StartsWith("model name", StringComparison.OrdinalIgnoreCase))
|
||||
{ name = line[(line.IndexOf(':') + 1)..].Trim(); break; }
|
||||
}
|
||||
catch { }
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
name = Run("bash", "-lc \"lscpu | grep -i 'Model name' | cut -d: -f2- | xargs\"");
|
||||
|
||||
// Socket count
|
||||
int sockets = 0;
|
||||
try
|
||||
{
|
||||
var set = new HashSet<string>(StringComparer.Ordinal);
|
||||
foreach (var dir in Directory.GetDirectories("/sys/devices/system/cpu", "cpu*"))
|
||||
{
|
||||
var dn = Path.GetFileName(dir);
|
||||
if (!dn.StartsWith("cpu") || !int.TryParse(dn[3..], out _)) continue;
|
||||
var p = Path.Combine(dir, "topology", "physical_package_id");
|
||||
if (File.Exists(p)) { var v = File.ReadAllText(p).Trim(); if (v != "") set.Add(v); }
|
||||
}
|
||||
sockets = set.Count;
|
||||
}
|
||||
catch { }
|
||||
if (sockets == 0)
|
||||
{
|
||||
var s = Run("bash", "-lc \"lscpu | grep -i 'Socket(s)' | awk -F: '{print $2}' | xargs\"");
|
||||
int.TryParse(s, out sockets);
|
||||
}
|
||||
|
||||
// Total RAM: /proc/meminfo (MemTotal: kB)
|
||||
ulong total = 0;
|
||||
try
|
||||
{
|
||||
foreach (var line in File.ReadLines("/proc/meminfo"))
|
||||
{
|
||||
if (line.StartsWith("MemTotal:", StringComparison.Ordinal))
|
||||
{
|
||||
var parts = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
// ví dụ: "MemTotal: 16367472 kB"
|
||||
if (parts.Length >= 2 && ulong.TryParse(parts[1], out var kb))
|
||||
total = kb * 1024UL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
if (total == 0)
|
||||
{
|
||||
var s = Run("bash", "-lc \"free -b | awk '/^Mem:/ {print $2}'\"");
|
||||
ulong.TryParse(s, out total);
|
||||
}
|
||||
|
||||
return new SysInfo(sockets, string.IsNullOrWhiteSpace(name) ? null : name, total);
|
||||
}
|
||||
|
||||
// ---------- macOS ----------
|
||||
static SysInfo GetMac()
|
||||
{
|
||||
var name = Run("sysctl", "-n machdep.cpu.brand_string");
|
||||
var sSockets = Run("sysctl", "-n hw.packages"); // số package
|
||||
int.TryParse(sSockets, out var sockets);
|
||||
|
||||
var mem = Run("sysctl", "-n hw.memsize");
|
||||
ulong.TryParse(mem, out var total);
|
||||
return new SysInfo(sockets, string.IsNullOrWhiteSpace(name) ? null : name.Trim(), total);
|
||||
}
|
||||
|
||||
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 txt = p.StandardOutput.ReadToEnd();
|
||||
p.WaitForExit(2000);
|
||||
return txt.Trim();
|
||||
}
|
||||
catch { return ""; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user