Windows为开发者开放了各式各样的接口,以便于实现对接系统管理、配置查看和变更、性能数据获取等功能,而由于.Net和Windows之间天生具备的紧密联系,使得相关功能的集成度更高,能比其它第三方的开发环境更轻松地实现这些接口的调用。下面会演示如何:

  • 通过System.Management.ManagementObjectSearcher类获取CPU使用率(wmi);
  • 通过Microsoft.VisualBasic.Devices.ComputerInfo获取系统的可用内存和总内存;
  • 通过System.Net.NetworkInformation.NetworkInterface获取网卡;
  • 使用PerformanceCounter获取网卡上下行流量;
  • 通过System.Management.ManagementObject对象按指定的路径获取电脑各分区情况(wmi)。

因为本系列的目的在于如何获得系统的性能数据,所以相关度不是很高的信息不会花费精力去讲述如何获取。当然,如果现实中碰到了这样的需求,绝大部分也可以依靠以上渠道进行获取。

* 在这先插一个如何快速准确定位自己的物理网卡的小技巧,想知道为什么会有这种需求,可以在命令提示符窗口输入ipconfig,这时可以发现获取系统网卡时,返回的网卡列表里会包含所有列出来的无线、物理、蓝牙、甚至各种VPN或ADSL拨号的网络连接。要通过程序区分这些连接,将会是一项比较烦琐的任务。
这个方法的原理是:使用一个TcpClient向外网资源建立一个网络连接(比如连接某个网站的443端口,或某台POP3服务器的110端口),建立完成后,即可获取到TcpClient所用Socket的本地IP地址,这个地址一定是访问外网所用的网卡的IP,绝无可能出错。然后再遍历本地所有网卡,谁的IP和TcpClient的本地IP一致,谁就是外网网卡。

    class Program
    {
        static void Main(string[] args)
        {
            ManagementObjectSearcher searcher;
            ManagementClass disksClass = new ManagementClass("Win32_Volume");

            //通过访问百度来获取Socket本地IP,再遍历本地网卡,
            //定位到网卡IP与Socket本地IP一致的那块网卡,即是外网网卡。
            TcpClient client = new TcpClient();
            client.BeginConnect("www.baidu.com", 443, null, null);
            Thread.Sleep(2000);
            string ip = ((IPEndPoint)client.Client.LocalEndPoint).Address.ToString();
            var adapter =
                NetworkInterface.GetAllNetworkInterfaces().
                First(n => n.GetIPProperties().UnicastAddresses.Any(i => i.Address.ToString() == ip));
            client.Close();
            PerformanceCounter speedIn =
                new PerformanceCounter("Network Interface", "Bytes Received/sec", adapter.Description);
            PerformanceCounter speedOut =
                new PerformanceCounter("Network Interface", "Bytes Sent/sec", adapter.Description);

            while (true)
            {
                Console.Clear();

                Console.WriteLine("分区使用情况:");
                ManagementObjectCollection disks = disksClass.GetInstances();
                foreach (ManagementObject disk in disks)
                {
                    string volName = disk["DriveLetter"]?.ToString();
                    if (string.IsNullOrEmpty(volName)) continue;
                    Console.WriteLine(
                        $"{volName}\tFileSystem: {disk["FileSystem"]}]" +
                        $"\t剩余:{(Convert.ToDouble(disk["FreeSpace"]) / Math.Pow(2, 30)).ToString("0.00")}GB " +
                        $"of {(Convert.ToDouble(disk["Capacity"]) / Math.Pow(2, 30)).ToString("0.00")}GB");
                }

                Console.WriteLine("\r\n网卡流量情况:");
                double inMB = speedIn.NextValue() / Math.Pow(2, 20);
                double outMB = speedOut.NextValue() / Math.Pow(2, 20);
                Console.WriteLine(
                    $"速度\tin: {inMB.ToString("0.00")} MB/s, " +
                    $"out: {outMB.ToString("0.00")} MB/s, " +
                    $"total {(inMB + outMB).ToString("0.00")} MB/s");

                searcher =
                    new ManagementObjectSearcher("select * from Win32_Processor");
                foreach (ManagementObject cpu in searcher.Get())
                {
                    var clock = ((uint)cpu["CurrentClockSpeed"]) / 1000.0;
                    Console.WriteLine($"\r\n{cpu["DeviceID"]}, {cpu["NumberOfCores"]}核{cpu["ThreadCount"]}线程," +
                        $"频率{clock.ToString("0.00GHz")},使用率: {cpu["LoadPercentage"]}% ");
                }
                Microsoft.VisualBasic.Devices.ComputerInfo myInfo =
                    new Microsoft.VisualBasic.Devices.Computer().Info;
                double memoryFree = myInfo.AvailablePhysicalMemory >> 20;
                double memoryTotal = myInfo.TotalPhysicalMemory >> 20;
                Console.WriteLine(
                    $"\r\n内存:\t总容量: {memoryTotal}M\t剩余: {memoryFree}M\t已使用: {memoryTotal - memoryFree}M " +
                    $"({(1 - memoryFree * 1.0 / memoryTotal).ToString("0.00%")})");

                Thread.Sleep(2000);

            }
        }
    }
分类: articles