update news & events
This commit is contained in:
95
TWASys-App/Models/ServerInfo/HwIdReader.cs
Normal file
95
TWASys-App/Models/ServerInfo/HwIdReader.cs
Normal file
@ -0,0 +1,95 @@
|
||||
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 ""; }
|
||||
}
|
||||
}
|
||||
}
|
||||
123
TWASys-App/Models/ServerInfo/NetUtils.cs
Normal file
123
TWASys-App/Models/ServerInfo/NetUtils.cs
Normal file
@ -0,0 +1,123 @@
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace TWASys_App.Models.ServerInfo
|
||||
{
|
||||
public class NetUtils
|
||||
{
|
||||
public static string? GetPrimaryPrivateIPv4String()
|
||||
{
|
||||
if (!Socket.OSSupportsIPv4) return null;
|
||||
try
|
||||
{
|
||||
using var s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
s.Connect(new IPEndPoint(IPAddress.Parse("8.8.8.8"), 53));
|
||||
return (s.LocalEndPoint as IPEndPoint)?.Address.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback: liệt kê NIC
|
||||
return GetAllPrivateIPsStrings().FirstOrDefault(ip => ip.Contains('.'));
|
||||
}
|
||||
}
|
||||
|
||||
public static string? GetPrimaryPrivateIPv6String()
|
||||
{
|
||||
if (!Socket.OSSupportsIPv6) return null;
|
||||
try
|
||||
{
|
||||
using var s = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
|
||||
s.Connect(new IPEndPoint(IPAddress.Parse("2001:4860:4860::8888"), 53));
|
||||
var ip = (s.LocalEndPoint as IPEndPoint)?.Address;
|
||||
return ip is null ? null : FormatIPv6WithScope(ip);
|
||||
}
|
||||
catch
|
||||
{
|
||||
var ip = FirstIPv6_ByEnum();
|
||||
return ip is null ? null : FormatIPv6WithScope(ip);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetAllPrivateIPsStrings()
|
||||
{
|
||||
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if (ni.OperationalStatus != OperationalStatus.Up) continue;
|
||||
if (ni.NetworkInterfaceType is NetworkInterfaceType.Loopback or NetworkInterfaceType.Tunnel) continue;
|
||||
|
||||
var idx = ni.GetIPProperties().GetIPv6Properties()?.Index;
|
||||
|
||||
foreach (var ua in ni.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
var ip = ua.Address;
|
||||
if (IPAddress.IsLoopback(ip)) continue;
|
||||
|
||||
if (ip.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
if (IsPrivateIPv4(ip)) yield return ip.ToString();
|
||||
}
|
||||
else if (ip.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
if (IsPrivateIPv6(ip)) yield return FormatIPv6WithScope(ip, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- PUBLIC IP (string) ----------
|
||||
public static async Task<string?> GetPublicIPv4Async(CancellationToken ct = default) =>
|
||||
await FetchFirstAsync(new[] { "https://api.ipify.org", "https://checkip.amazonaws.com", "https://ipv4.icanhazip.com" }, ct);
|
||||
|
||||
public static async Task<string?> GetPublicIPv6Async(CancellationToken ct = default) =>
|
||||
await FetchFirstAsync(new[] { "https://api6.ipify.org", "https://ipv6.icanhazip.com", "https://ifconfig.co/ip" }, ct);
|
||||
|
||||
public static async Task<string?> GetPublicIpAsync(bool preferIPv6 = false, CancellationToken ct = default) =>
|
||||
preferIPv6 ? await GetPublicIPv6Async(ct) ?? await GetPublicIPv4Async(ct)
|
||||
: await GetPublicIPv4Async(ct) ?? await GetPublicIPv6Async(ct);
|
||||
|
||||
// ---------- helpers ----------
|
||||
static async Task<string?> FetchFirstAsync(IEnumerable<string> urls, CancellationToken ct)
|
||||
{
|
||||
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(3) };
|
||||
foreach (var u in urls)
|
||||
try
|
||||
{
|
||||
var s = (await http.GetStringAsync(u, ct)).Trim();
|
||||
if (!string.IsNullOrWhiteSpace(s)) return s;
|
||||
}
|
||||
catch { /* thử URL kế */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
static IPAddress? FirstIPv6_ByEnum() =>
|
||||
NetworkInterface.GetAllNetworkInterfaces()
|
||||
.Where(n => n.OperationalStatus == OperationalStatus.Up &&
|
||||
n.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
|
||||
n.NetworkInterfaceType != NetworkInterfaceType.Tunnel)
|
||||
.SelectMany(n => n.GetIPProperties().UnicastAddresses)
|
||||
.Select(u => u.Address)
|
||||
.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetworkV6);
|
||||
|
||||
static bool IsPrivateIPv4(IPAddress ip)
|
||||
{
|
||||
var b = ip.GetAddressBytes();
|
||||
return b[0] == 10 || (b[0] == 172 && b[1] is >= 16 and <= 31) || (b[0] == 192 && b[1] == 168);
|
||||
}
|
||||
static bool IsPrivateIPv6(IPAddress ip)
|
||||
{
|
||||
var b = ip.GetAddressBytes();
|
||||
return ((b[0] & 0xFE) == 0xFC) || (b[0] == 0xFE && (b[1] & 0xC0) == 0x80); // fc00::/7, fe80::/10
|
||||
}
|
||||
|
||||
// KHÔNG đụng IPAddress.ScopeId. Nếu link-local, thêm scope = index của NIC.
|
||||
static string FormatIPv6WithScope(IPAddress ip, int? nicIndex = null)
|
||||
{
|
||||
if (ip.AddressFamily != AddressFamily.InterNetworkV6) return ip.ToString();
|
||||
var b = ip.GetAddressBytes();
|
||||
bool linkLocal = b[0] == 0xFE && (b[1] & 0xC0) == 0x80;
|
||||
if (linkLocal && nicIndex is int idx) return $"{ip}%{idx}";
|
||||
return ip.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
128
TWASys-App/Models/ServerInfo/OsInfoReader.cs
Normal file
128
TWASys-App/Models/ServerInfo/OsInfoReader.cs
Normal file
@ -0,0 +1,128 @@
|
||||
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 ""; }
|
||||
}
|
||||
}
|
||||
}
|
||||
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