SystemInfo.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. using Masuit.Tools.Logging;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Linq;
  7. using System.Management;
  8. using System.Net;
  9. using System.Net.NetworkInformation;
  10. using System.Runtime.InteropServices;
  11. using System.Text;
  12. namespace Masuit.Tools.Hardware
  13. {
  14. /// <summary>
  15. /// 硬件信息,部分功能需要C++支持,仅支持Windows系统
  16. /// </summary>
  17. public static partial class SystemInfo
  18. {
  19. #region 字段
  20. private const int GwHwndfirst = 0;
  21. private const int GwHwndnext = 2;
  22. private const int GwlStyle = -16;
  23. private const int WsVisible = 268435456;
  24. private const int WsBorder = 8388608;
  25. private static readonly PerformanceCounter PcCpuLoad; //CPU计数器
  26. private static readonly PerformanceCounter MemoryCounter = new PerformanceCounter();
  27. private static readonly PerformanceCounter CpuCounter = new PerformanceCounter();
  28. private static readonly PerformanceCounter DiskReadCounter = new PerformanceCounter();
  29. private static readonly PerformanceCounter DiskWriteCounter = new PerformanceCounter();
  30. private static readonly string[] InstanceNames;
  31. private static readonly PerformanceCounter[] NetRecvCounters;
  32. private static readonly PerformanceCounter[] NetSentCounters;
  33. #endregion
  34. #region 构造函数
  35. /// <summary>
  36. /// 静态构造函数
  37. /// </summary>
  38. static SystemInfo()
  39. {
  40. //初始化CPU计数器
  41. PcCpuLoad = new PerformanceCounter("Processor", "% Processor Time", "_Total")
  42. {
  43. MachineName = "."
  44. };
  45. PcCpuLoad.NextValue();
  46. //CPU个数
  47. ProcessorCount = Environment.ProcessorCount;
  48. //获得物理内存
  49. try
  50. {
  51. using var mc = new ManagementClass("Win32_ComputerSystem");
  52. using var moc = mc.GetInstances();
  53. foreach (var mo in moc)
  54. {
  55. if (mo["TotalPhysicalMemory"] != null)
  56. {
  57. PhysicalMemory = long.Parse(mo["TotalPhysicalMemory"].ToString());
  58. }
  59. }
  60. var cat = new PerformanceCounterCategory("Network Interface");
  61. InstanceNames = cat.GetInstanceNames();
  62. NetRecvCounters = new PerformanceCounter[InstanceNames.Length];
  63. NetSentCounters = new PerformanceCounter[InstanceNames.Length];
  64. for (int i = 0; i < InstanceNames.Length; i++)
  65. {
  66. NetRecvCounters[i] = new PerformanceCounter();
  67. NetSentCounters[i] = new PerformanceCounter();
  68. }
  69. CompactFormat = false;
  70. }
  71. catch (Exception e)
  72. {
  73. LogManager.Error(e);
  74. }
  75. }
  76. #endregion
  77. private static bool CompactFormat { get; set; }
  78. #region CPU核心
  79. /// <summary>
  80. /// 获取CPU核心数
  81. /// </summary>
  82. public static int ProcessorCount { get; }
  83. #endregion
  84. #region CPU占用率
  85. /// <summary>
  86. /// 获取CPU占用率 %
  87. /// </summary>
  88. public static float CpuLoad => PcCpuLoad.NextValue();
  89. #endregion
  90. #region 可用内存
  91. /// <summary>
  92. /// 获取可用内存
  93. /// </summary>
  94. public static long MemoryAvailable
  95. {
  96. get
  97. {
  98. try
  99. {
  100. using var mos = new ManagementClass("Win32_OperatingSystem");
  101. foreach (var mo in mos.GetInstances())
  102. {
  103. if (mo["FreePhysicalMemory"] != null)
  104. {
  105. return 1024 * long.Parse(mo["FreePhysicalMemory"].ToString());
  106. }
  107. }
  108. return 0;
  109. }
  110. catch (Exception)
  111. {
  112. return 0;
  113. }
  114. }
  115. }
  116. #endregion
  117. #region 物理内存
  118. /// <summary>
  119. /// 获取物理内存
  120. /// </summary>
  121. public static long PhysicalMemory { get; }
  122. #endregion
  123. #region 查找所有应用程序标题
  124. /// <summary>
  125. /// 查找所有应用程序标题
  126. /// </summary>
  127. /// <param name="handle">应用程序标题范型</param>
  128. /// <returns>所有应用程序集合</returns>
  129. public static ArrayList FindAllApps(int handle)
  130. {
  131. var apps = new ArrayList();
  132. int hwCurr = GetWindow(handle, GwHwndfirst);
  133. while (hwCurr > 0)
  134. {
  135. int IsTask = WsVisible | WsBorder;
  136. int lngStyle = GetWindowLongA(hwCurr, GwlStyle);
  137. bool taskWindow = (lngStyle & IsTask) == IsTask;
  138. if (taskWindow)
  139. {
  140. int length = GetWindowTextLength(new IntPtr(hwCurr));
  141. StringBuilder sb = new StringBuilder(2 * length + 1);
  142. GetWindowText(hwCurr, sb, sb.Capacity);
  143. string strTitle = sb.ToString();
  144. if (!string.IsNullOrEmpty(strTitle))
  145. {
  146. apps.Add(strTitle);
  147. }
  148. }
  149. hwCurr = GetWindow(hwCurr, GwHwndnext);
  150. }
  151. return apps;
  152. }
  153. #endregion
  154. #region 获取CPU的数量
  155. /// <summary>
  156. /// 获取CPU的数量
  157. /// </summary>
  158. /// <returns>CPU的数量</returns>
  159. public static int GetCpuCount()
  160. {
  161. try
  162. {
  163. using var m = new ManagementClass("Win32_Processor");
  164. using var mn = m.GetInstances();
  165. return mn.Count;
  166. }
  167. catch (Exception)
  168. {
  169. return 0;
  170. }
  171. }
  172. #endregion
  173. #region 获取CPU信息
  174. private static List<ManagementBaseObject> _cpuObjects;
  175. /// <summary>
  176. /// 获取CPU信息
  177. /// </summary>
  178. /// <returns>CPU信息</returns>
  179. public static List<CpuInfo> GetCpuInfo()
  180. {
  181. try
  182. {
  183. using var mos = new ManagementObjectSearcher("SELECT * FROM Win32_Processor");
  184. using var moc = mos.Get();
  185. _cpuObjects ??= moc.AsParallel().Cast<ManagementBaseObject>().ToList();
  186. return _cpuObjects.Select(mo => new CpuInfo
  187. {
  188. CpuLoad = CpuLoad,
  189. NumberOfLogicalProcessors = ProcessorCount,
  190. CurrentClockSpeed = mo.Properties["CurrentClockSpeed"].Value.ToString(),
  191. Manufacturer = mo.Properties["Manufacturer"].Value.ToString(),
  192. MaxClockSpeed = mo.Properties["MaxClockSpeed"].Value.ToString(),
  193. Type = mo.Properties["Name"].Value.ToString(),
  194. DataWidth = mo.Properties["DataWidth"].Value.ToString(),
  195. SerialNumber = mo.Properties["ProcessorId"].Value.ToString(),
  196. DeviceID = mo.Properties["DeviceID"].Value.ToString(),
  197. NumberOfCores = Convert.ToInt32(mo.Properties["NumberOfCores"].Value),
  198. Temperature = GetCPUTemperature()
  199. }).ToList();
  200. }
  201. catch (Exception)
  202. {
  203. return new List<CpuInfo>();
  204. }
  205. }
  206. #endregion
  207. #region 获取内存信息
  208. /// <summary>
  209. /// 获取内存信息
  210. /// </summary>
  211. /// <returns>内存信息</returns>
  212. public static RamInfo GetRamInfo()
  213. {
  214. var info = new RamInfo
  215. {
  216. MemoryAvailable = GetFreePhysicalMemory(),
  217. PhysicalMemory = GetTotalPhysicalMemory(),
  218. TotalPageFile = GetTotalVirtualMemory(),
  219. AvailablePageFile = GetTotalVirtualMemory() - GetUsedVirtualMemory(),
  220. AvailableVirtual = 1 - GetUsageVirtualMemory(),
  221. TotalVirtual = 1 - GetUsedPhysicalMemory()
  222. };
  223. return info;
  224. }
  225. #endregion
  226. #region 获取CPU温度
  227. /// <summary>
  228. /// 获取CPU温度
  229. /// </summary>
  230. /// <returns>CPU温度</returns>
  231. public static float GetCPUTemperature()
  232. {
  233. try
  234. {
  235. string str = "";
  236. using var mos = new ManagementObjectSearcher(@"root\WMI", "select * from MSAcpi_ThermalZoneTemperature");
  237. var moc = mos.Get();
  238. foreach (var mo in moc)
  239. {
  240. str += mo.Properties["CurrentTemperature"].Value.ToString();
  241. }
  242. //这就是CPU的温度了
  243. float temp = (float.Parse(str) - 2732) / 10;
  244. return (float)Math.Round(temp, 2);
  245. }
  246. catch (Exception)
  247. {
  248. return 0;
  249. }
  250. }
  251. #endregion
  252. #region WMI接口获取CPU使用率
  253. /// <summary>
  254. /// WMI接口获取CPU使用率
  255. /// </summary>
  256. /// <returns></returns>
  257. public static string GetProcessorData()
  258. {
  259. float d = GetCounterValue(CpuCounter, "Processor", "% Processor Time", "_Total");
  260. return CompactFormat ? (int)d + "%" : d.ToString("F") + "%";
  261. }
  262. #endregion
  263. #region 获取虚拟内存使用率详情
  264. /// <summary>
  265. /// 获取虚拟内存使用率详情
  266. /// </summary>
  267. /// <returns></returns>
  268. public static string GetMemoryVData()
  269. {
  270. float d = GetCounterValue(MemoryCounter, "Memory", "% Committed Bytes In Use", null);
  271. var str = d.ToString("F") + "% (";
  272. d = GetCounterValue(MemoryCounter, "Memory", "Committed Bytes", null);
  273. str += FormatBytes(d) + " / ";
  274. d = GetCounterValue(MemoryCounter, "Memory", "Commit Limit", null);
  275. return str + FormatBytes(d) + ") ";
  276. }
  277. /// <summary>
  278. /// 获取虚拟内存使用率
  279. /// </summary>
  280. /// <returns></returns>
  281. public static float GetUsageVirtualMemory()
  282. {
  283. return GetCounterValue(MemoryCounter, "Memory", "% Committed Bytes In Use", null);
  284. }
  285. /// <summary>
  286. /// 获取虚拟内存已用大小
  287. /// </summary>
  288. /// <returns></returns>
  289. public static float GetUsedVirtualMemory()
  290. {
  291. return GetCounterValue(MemoryCounter, "Memory", "Committed Bytes", null);
  292. }
  293. /// <summary>
  294. /// 获取虚拟内存总大小
  295. /// </summary>
  296. /// <returns></returns>
  297. public static float GetTotalVirtualMemory()
  298. {
  299. return GetCounterValue(MemoryCounter, "Memory", "Commit Limit", null);
  300. }
  301. #endregion
  302. #region 获取物理内存使用率详情
  303. /// <summary>
  304. /// 获取物理内存使用率详情描述
  305. /// </summary>
  306. /// <returns></returns>
  307. public static string GetMemoryPData()
  308. {
  309. string s = QueryComputerSystem("totalphysicalmemory");
  310. float totalphysicalmemory = Convert.ToSingle(s);
  311. float d = GetCounterValue(MemoryCounter, "Memory", "Available Bytes", null);
  312. d = totalphysicalmemory - d;
  313. s = CompactFormat ? "%" : "% (" + FormatBytes(d) + " / " + FormatBytes(totalphysicalmemory) + ")";
  314. d /= totalphysicalmemory;
  315. d *= 100;
  316. return CompactFormat ? (int)d + s : d.ToString("F") + s;
  317. }
  318. /// <summary>
  319. /// 获取物理内存总数,单位B
  320. /// </summary>
  321. /// <returns></returns>
  322. public static float GetTotalPhysicalMemory()
  323. {
  324. string s = QueryComputerSystem("totalphysicalmemory");
  325. return s.TryConvertTo<float>();
  326. }
  327. /// <summary>
  328. /// 获取空闲的物理内存数,单位B
  329. /// </summary>
  330. /// <returns></returns>
  331. public static float GetFreePhysicalMemory()
  332. {
  333. return GetCounterValue(MemoryCounter, "Memory", "Available Bytes", null);
  334. }
  335. /// <summary>
  336. /// 获取已经使用了的物理内存数,单位B
  337. /// </summary>
  338. /// <returns></returns>
  339. public static float GetUsedPhysicalMemory()
  340. {
  341. return GetTotalPhysicalMemory() - GetFreePhysicalMemory();
  342. }
  343. #endregion
  344. #region 获取硬盘的读写速率
  345. /// <summary>
  346. /// 获取硬盘的读写速率
  347. /// </summary>
  348. /// <param name="dd">读或写</param>
  349. /// <returns></returns>
  350. public static float GetDiskData(DiskData dd) => dd == DiskData.Read ? GetCounterValue(DiskReadCounter, "PhysicalDisk", "Disk Read Bytes/sec", "_Total") : dd == DiskData.Write ? GetCounterValue(DiskWriteCounter, "PhysicalDisk", "Disk Write Bytes/sec", "_Total") : dd == DiskData.ReadAndWrite ? GetCounterValue(DiskReadCounter, "PhysicalDisk", "Disk Read Bytes/sec", "_Total") + GetCounterValue(DiskWriteCounter, "PhysicalDisk", "Disk Write Bytes/sec", "_Total") : 0;
  351. #endregion
  352. #region 获取网络的传输速率
  353. /// <summary>
  354. /// 获取网络的传输速率
  355. /// </summary>
  356. /// <param name="nd">上传或下载</param>
  357. /// <returns></returns>
  358. public static float GetNetData(NetData nd)
  359. {
  360. if (InstanceNames.Length == 0)
  361. {
  362. return 0;
  363. }
  364. float d = 0;
  365. for (int i = 0; i < InstanceNames.Length; i++)
  366. {
  367. float receied = GetCounterValue(NetRecvCounters[i], "Network Interface", "Bytes Received/sec", InstanceNames[i]);
  368. float send = GetCounterValue(NetSentCounters[i], "Network Interface", "Bytes Sent/sec", InstanceNames[i]);
  369. switch (nd)
  370. {
  371. case NetData.Received:
  372. d += receied;
  373. break;
  374. case NetData.Sent:
  375. d += send;
  376. break;
  377. case NetData.ReceivedAndSent:
  378. d += receied + send;
  379. break;
  380. default:
  381. d += 0;
  382. break;
  383. }
  384. }
  385. return d;
  386. }
  387. #endregion
  388. /// <summary>
  389. /// 获取网卡硬件地址
  390. /// </summary>
  391. /// <returns></returns>
  392. public static IList<string> GetMacAddress()
  393. {
  394. //获取网卡硬件地址
  395. try
  396. {
  397. IList<string> list = new List<string>();
  398. using var mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
  399. using var moc = mc.GetInstances();
  400. foreach (var mo in moc)
  401. {
  402. if ((bool)mo["IPEnabled"])
  403. {
  404. list.Add(mo["MacAddress"].ToString());
  405. }
  406. }
  407. return list;
  408. }
  409. catch (Exception)
  410. {
  411. return new List<string>();
  412. }
  413. }
  414. /// <summary>
  415. /// 获取当前使用的IP
  416. /// </summary>
  417. /// <returns></returns>
  418. public static IPAddress GetLocalUsedIP()
  419. {
  420. return NetworkInterface.GetAllNetworkInterfaces().OrderByDescending(c => c.Speed).Where(c => c.NetworkInterfaceType != NetworkInterfaceType.Loopback && c.OperationalStatus == OperationalStatus.Up).SelectMany(n => n.GetIPProperties().UnicastAddresses.Select(u => u.Address)).FirstOrDefault();
  421. }
  422. /// <summary>
  423. /// 获取本机所有的ip地址
  424. /// </summary>
  425. /// <returns></returns>
  426. public static List<UnicastIPAddressInformation> GetLocalIPs()
  427. {
  428. var interfaces = NetworkInterface.GetAllNetworkInterfaces().OrderByDescending(c => c.Speed).Where(c => c.NetworkInterfaceType != NetworkInterfaceType.Loopback && c.OperationalStatus == OperationalStatus.Up); //所有网卡信息
  429. return interfaces.SelectMany(n => n.GetIPProperties().UnicastAddresses).ToList();
  430. }
  431. #region 将速度值格式化成字节单位
  432. /// <summary>
  433. /// 将速度值格式化成字节单位
  434. /// </summary>
  435. /// <param name="bytes"></param>
  436. /// <returns></returns>
  437. public static string FormatBytes(this double bytes)
  438. {
  439. int unit = 0;
  440. while (bytes > 1024)
  441. {
  442. bytes /= 1024;
  443. ++unit;
  444. }
  445. string s = CompactFormat ? ((int)bytes).ToString() : bytes.ToString("F") + " ";
  446. return s + (Unit)unit;
  447. }
  448. #endregion
  449. #region 查询计算机系统信息
  450. /// <summary>
  451. /// 获取计算机开机时间
  452. /// </summary>
  453. /// <returns>datetime</returns>
  454. public static DateTime BootTime()
  455. {
  456. var query = new SelectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem WHERE Primary='true'");
  457. using var searcher = new ManagementObjectSearcher(query);
  458. foreach (var mo in searcher.Get())
  459. {
  460. return ManagementDateTimeConverter.ToDateTime(mo.Properties["LastBootUpTime"].Value.ToString());
  461. }
  462. return DateTime.Now - TimeSpan.FromMilliseconds(Environment.TickCount & int.MaxValue);
  463. }
  464. /// <summary>
  465. /// 查询计算机系统信息
  466. /// </summary>
  467. /// <param name="type">类型名</param>
  468. /// <returns></returns>
  469. public static string QueryComputerSystem(string type)
  470. {
  471. try
  472. {
  473. string str = null;
  474. var mos = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
  475. foreach (var mo in mos.Get())
  476. {
  477. str = mo[type].ToString();
  478. }
  479. return str;
  480. }
  481. catch (Exception e)
  482. {
  483. return "未能获取到当前计算机系统信息,可能是当前程序无管理员权限,如果是web应用程序,请将应用程序池的高级设置中的进程模型下的标识设置为:LocalSystem;如果是普通桌面应用程序,请提升管理员权限后再操作。异常信息:" + e.Message;
  484. }
  485. }
  486. #endregion
  487. #region 获取环境变量
  488. /// <summary>
  489. /// 获取环境变量
  490. /// </summary>
  491. /// <param name="type">环境变量名</param>
  492. /// <returns></returns>
  493. public static string QueryEnvironment(string type) => Environment.ExpandEnvironmentVariables(type);
  494. #endregion
  495. #region 获取磁盘空间
  496. private static readonly List<DiskInfo> DiskInfos = new();
  497. /// <summary>
  498. /// 获取磁盘可用空间
  499. /// </summary>
  500. /// <returns></returns>
  501. public static List<DiskInfo> GetDiskInfo()
  502. {
  503. try
  504. {
  505. if (DiskInfos.Count > 0)
  506. {
  507. return DiskInfos;
  508. }
  509. using var mc = new ManagementClass("Win32_DiskDrive");
  510. using var moc = mc.GetInstances();
  511. foreach (var mo in moc)
  512. {
  513. DiskInfos.Add(new DiskInfo()
  514. {
  515. Total = float.Parse(mo["Size"].ToString()),
  516. Model = mo["Model"].ToString(),
  517. SerialNumber = mo["SerialNumber"].ToString(),
  518. });
  519. }
  520. return DiskInfos;
  521. }
  522. catch (Exception)
  523. {
  524. return new List<DiskInfo>();
  525. }
  526. }
  527. #endregion
  528. private static float GetCounterValue(PerformanceCounter pc, string categoryName, string counterName, string instanceName)
  529. {
  530. pc.CategoryName = categoryName;
  531. pc.CounterName = counterName;
  532. pc.InstanceName = instanceName;
  533. return pc.NextValue();
  534. }
  535. #region Win32API声明
  536. #pragma warning disable 1591
  537. [DllImport("User32")]
  538. public static extern int GetWindow(int hWnd, int wCmd);
  539. [DllImport("User32")]
  540. public static extern int GetWindowLongA(int hWnd, int wIndx);
  541. [DllImport("user32.dll")]
  542. public static extern bool GetWindowText(int hWnd, StringBuilder title, int maxBufSize);
  543. [DllImport("user32", CharSet = CharSet.Auto)]
  544. public static extern int GetWindowTextLength(IntPtr hWnd);
  545. #pragma warning restore 1591
  546. #endregion
  547. }
  548. }