侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

ASP.NET 任务管理器

2023-11-23 星期四 / 0 评论 / 0 点赞 / 37 阅读 / 16638 字

最近需要做一个网页动态展示服务器CPU,内存等信息,类似windows任务管理器的B/S版。因为服务器是windows server 2008,所以采用了ASP.NET来开发,主要涉及2部分,一是读取

最近需要做一个网页动态展示服务器CPU,内存等信息,类似windows任务管理器的B/S版。因为服务器是windows server 2008,所以采用了ASP.NET来开发,主要涉及2部分,一是读取系统信息;二是动态展示。

 

读取系统信息分为CPU,内存,硬盘和网络四部分。其中内存和硬盘信息都用了System.Management类库,CPU信息则用到了System.Diagnostics命名空间下的PerformanceCounter类,网络信息主要利用System.Net.NetworkInformation命名空间下的类。源代码如下:

public struct DiskInfo{    public string Name;    public long Free;    public long Size;}public class SystemInfo{	private const string CategoryName = "Processor";	private const string CounterName = "% Processor Time";	private const string InstanceName = "_Total";	private static PerformanceCounter pc = new PerformanceCounter(CategoryName, CounterName, InstanceName);	private static NetworkInterface[] nicArr;  //网卡集合	private static long sent = 0, received = 0;	public static string NetName = "";	/// <summary>	/// CPU 使用率,可参考	/// https://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter(v=vs.110).aspx	/// https://msdn.microsoft.com/en-us/library/w8f5kw2e(v=vs.110).aspx	/// 其中CategoryName主要有如下几种	/// Cache, Memory, Objects, PhysicalDisk, Process, Processor, Server, System, Thread categories	/// 而CounterName可以通过Performance Monitor查看已有的(在Performance Monitor中,	/// 选中Performance Monitor,点击添加“+”,即可看到)。	/// </summary>	/// <returns>CPU使用百分比</returns>	public static float CPUrate()	{		// 单个CPU使用情况要除以CPU个数 Environment.ProcessorCount,但是windows似乎每个CPU使用率并不完全相同		return pc.NextValue();	}	/// <summary>	/// 机器总的内存数,注意该值可能不精确。可参考	/// https://msdn.microsoft.com/en-us/library/aa394102(v=vs.85).aspx	/// 还可以使用 Win32_PhysicalMemory 类中的 Capacity 变量来获得内存信息,可参考	/// https://msdn.microsoft.com/en-us/library/aa394347(v=vs.85).aspx	/// </summary>	/// <returns>总内存大小字节数,单位是Bytes</returns>	public static long TotalMemory()	{		long m_PhysicalMemory = 0;		ManagementClass mc = new ManagementClass("Win32_ComputerSystem");		ManagementObjectCollection moc = mc.GetInstances();		foreach (ManagementObject mo in moc)		{			if (mo["TotalPhysicalMemory"] != null)			{				m_PhysicalMemory = long.Parse(mo["TotalPhysicalMemory"].ToString());			}		}		return m_PhysicalMemory;	}	/// <summary>	/// 已用内存信息,可参考	/// https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx	/// </summary>	/// <returns>返回已使用的内存大小,单位是Bytes</returns>	public static long MemUsage()	{		long m_PhysicalMemory = 0;		long availablebytes = 0;		ManagementClass mos = new ManagementClass("Win32_OperatingSystem");		foreach (ManagementObject mo in mos.GetInstances())		{			if (mo["FreePhysicalMemory"] != null)			{				availablebytes = 1024 * long.Parse(mo["FreePhysicalMemory"].ToString());			}			if (mo["TotalVisibleMemorySize"] != null)			{				m_PhysicalMemory = 1024 * long.Parse(mo["TotalVisibleMemorySize"].ToString());			}		}		return m_PhysicalMemory - availablebytes;	}	/// <summary>	/// 硬盘使用情况,可参考	/// https://msdn.microsoft.com/en-us/library/aa394173(v=vs.85).aspx	/// </summary>	/// <returns>返回了硬盘基本信息,包括名称,大小,可用大小,单位为Bytes</returns>	public static DiskInfo[] DiskUsage()	{		ManagementClass diskClass = new ManagementClass("Win32_LogicalDisk");		ManagementObjectCollection disks = diskClass.GetInstances();		List<DiskInfo> info = new List<DiskInfo>();		foreach (ManagementObject disk in disks)		{			if (int.Parse(disk["DriveType"].ToString()) == (int)DriveType.Fixed)			{				string name = disk["Name"].ToString();				long size = long.Parse(disk["Size"].ToString());				long free = long.Parse(disk["FreeSpace"].ToString());				info.Add(new DiskInfo() { Name = name, Size = size, Free = free });			}		}		return info.ToArray();	}	/// <summary>	/// 网络传输信息,可参考	/// https://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface(v=vs.110).aspx	/// </summary>    /// <param name="ipAddress">要监控的ip地址</param>    /// <param name="received">下载字节数,单位为Bytes</param>    /// <param name="sent">上传字节数,单位为Bytes</param>	public static void NetUsage(string ipAddress, out long received, out long sent)	{		nicArr = NetworkInterface.GetAllNetworkInterfaces();		foreach (NetworkInterface net in nicArr)		{			IPInterfaceProperties ipProperty = net.GetIPProperties();			// 该网卡为以太网且有连接			if (net.NetworkInterfaceType == NetworkInterfaceType.Ethernet && net.OperationalStatus == OperationalStatus.Up)			{				foreach (var ip in ipProperty.UnicastAddresses)				{					// 如果为IPv4地址					if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)					{						NetName = ip.Address.ToString();  // 获取ip地址					}				}				if (NetName == ipAddress)				{					IPv4InterfaceStatistics curIPfs = net.GetIPv4Statistics();					info.Received = curIPfs.BytesReceived - received;					info.Sent = curIPfs.BytesSent - sent;					sent = curIPfs.BytesSent;					received = curIPfs.BytesReceived;					break;				}			}		}	}}

为了方便,把相关的几个网址记录如下:

  • CPU 使用率,可参考

https://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/w8f5kw2e(v=vs.110).aspx

  • 内存信息,可参考

https://msdn.microsoft.com/en-us/library/aa394102(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/aa394347(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx

  • 硬盘使用情况,可参考

https://msdn.microsoft.com/en-us/library/aa394173(v=vs.85).aspx

  • 网络传输信息,可参考

https://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface(v=vs.110).aspx

 

动态展示主要用到ASP.NET chart控件和updatepanel控件。鉴于硬盘信息变化实时性不强,因此用两个panel分别放置动态的(CPU,内存和网络)和静态的(硬盘)chart。

aspx文件主要代码如下:

<asp:Panel ID="DynamicPanel" runat="server">	<asp:ScriptManager ID="ScriptManager1" runat="server">	</asp:ScriptManager>	<asp:UpdatePanel ID="UpdatePanel1" runat="server">		<ContentTemplate>            <%--每2秒(2000毫秒)更新一次--%>			<asp:Timer ID="timerTest" runat="server" Interval="2000"				OnTick="timer_Tick">			</asp:Timer>			<asp:Chart ID="Chart1" runat="server" Width="640px" Height="360px">				<Series>					<asp:Series Name="Series1" ChartType="SplineArea" Color="PowderBlue" BorderColor="Blue">					</asp:Series>				</Series>				<ChartAreas>					<asp:ChartArea Name="ChartArea1" AlignmentOrientation="Horizontal">						<AxisX>							<MajorGrid LineDashStyle="Dash" />							<LabelStyle Enabled="false" />						</AxisX>						<AxisY Title="Y Axis" TitleFont="微软雅黑,16pt" TitleForeColor="RoyalBlue">							<MajorGrid LineDashStyle="Dash" />						</AxisY>					</asp:ChartArea>				</ChartAreas>				<Legends>					<asp:Legend Name="Legend1" Enabled="False"></asp:Legend>				</Legends>			</asp:Chart>		</ContentTemplate>	</asp:UpdatePanel></asp:Panel><asp:Panel ID="StaticPanel" runat="server" ScrollBars="Vertical"></asp:Panel>

aspx.cs主要代码如下:

public struct NetInfo{    public long Sent;	public long Received;}public partial class SysInfoChart : System.Web.UI.Page{	private static string InfoType = "cpu";      // 该变量用于记录当前状态	private static float m_timeInterval = 2;     // 刷新时间,用于计算网络传输速率	private static bool m_loaded = false;        // 该变量用于控制单次载入	private const int gridX = 10;                // 最多显示10个数据点    public static List<float> ChartData = new List<float>();    public static List<NetInfo> NetData = new List<NetInfo>();    public static DiskInfo[] DiskData;    public static int TickNum = 0;    public const float GBFactor = 1024 * 1024 * 1024.0f;    public const float MBFactor = 1024 * 1024.0f;    public const float KBFactor = 1024.0f;    public static float TotalMemory = SystemInfo.TotalMemory() / MBFactor;	protected void Page_Load(object sender, EventArgs e)	{		if (!m_loaded)		{			m_timeInterval = timerTest.Interval / 1000.0f;			if (InfoType == "disk")			{				DynamicPanel.Visible = false;				StaticPanel.Visible = true;			}			else			{				DynamicPanel.Visible = true;				StaticPanel.Visible = false;			}			TickNum = 0;            ChartData.Clear();            NetData.Clear();			m_loaded = true;		}				}	protected void timer_Tick(object sender, EventArgs e)	{		TickNum += 1;				switch(InfoType)		{			case "cpu":				ChartData.Add(SystemInfo.CPUrate());				CPU_Chart_Load(sender, e);				break;			case "mem":				ChartData.Add(SystemInfo.MemUsage() / MBFactor);				Mem_Chart_Load();				break;			case "disk":				DiskData = SystemInfo.DiskUsage();				Disk_Chart_Load();				break;			case "net":			    long received, sent;                // 此处"192.168.1.1"为本机ip地址			    SystemInfo.NetUsage("192.168.1.1", out received, out sent);				NetData.Add(new NetInfo(){ Received = received, Sent = sent });				Net_Chart_Load();				break;			default:				break;		}	}	/// <summary>	/// 调整数据,只显示固定数量的数据点。如果数据量不足,则显示0	/// 该实现不好,应该用固定大小Queue,不过时间不够,先凑合用	/// </summary>	/// <param name="dt">要显示的数据表</param>	private void DataLoad(ref DataTable dt)	{		if (ChartData.Count >= gridX)  // 如果数据量多于要显示的		{			int index = ChartData.Count - gridX;			for (int i = 0; i < gridX; i++)			{				dt.Rows.Add(i, ChartData[index + i]);			}		}		else  // 如果数据量不足		{			int index = gridX - ChartData.Count;			for (int i = 0; i < gridX; i++)			{				if (i < index)				{					dt.Rows.Add(i, 0);				}				else				{					dt.Rows.Add(i, ChartData[i - index]);				}			}		}	}	/// <summary>	/// 调整数据,只显示固定数量的数据点。如果数据量不足,则显示0。专为网络数据用。	/// 将来最好和上一个函数整合一下,时间不够凑合用	/// </summary>	/// <param name="dt">要显示的数据表</param>	private void DataLoad2(ref DataTable dt)	{		if (NetData.Count >= gridX)		{			int index = NetData.Count - gridX;			for (int i = 0; i < gridX; i++)			{				int tmp = index + i;				float divider = KBFactor * m_timeInterval;				dt.Rows.Add(i, NetData[tmp].Sent / divider,					NetData[tmp].Received / divider,					NetData[tmp].MaxSpeed / divider);			}		}		else		{			int index = gridX - NetData.Count;			for (int i = 0; i < gridX; i++)			{				if (i < index)				{					dt.Rows.Add(i, 0, 0, 0);				}				else				{					int tmp = i - index;					float divider = KBFactor * m_timeInterval;					dt.Rows.Add(i, NetData[tmp].Sent / divider,						NetData[tmp].Received / divider,						NetData[tmp].MaxSpeed / divider);				}			}		}	}	protected void CPU_Chart_Load(object sender, EventArgs e)	{		DataTable m_dt = new DataTable();		m_dt.Columns.Add("时间", typeof(int));		m_dt.Columns.Add("CPU 占用率 (%)", typeof(float));		DataLoad(ref m_dt);		Chart1.DataSource = m_dt;				Chart1.Series["Series1"].XValueMember = "时间";		Chart1.Series["Series1"].YValueMembers = "CPU 占用率 (%)";		Chart1.ChartAreas["ChartArea1"].AxisY.Title = "CPU 占用率 (%)";		Chart1.ChartAreas["ChartArea1"].AxisY.Minimum = 0;		Chart1.ChartAreas["ChartArea1"].AxisY.Maximum = 100;		Chart1.DataBind();	}	protected void Mem_Chart_Load()	{		DataTable m_dt = new DataTable();		m_dt.Columns.Add("时间", typeof(int));		m_dt.Columns.Add("内存占用", typeof(float));		DataLoad(ref m_dt);		Chart1.DataSource = m_dt;		Chart1.Series["Series1"].XValueMember = "时间";		Chart1.Series["Series1"].YValueMembers = "内存占用";		Chart1.ChartAreas["ChartArea1"].AxisY.Title = "内存占用 (MB)";		Chart1.ChartAreas["ChartArea1"].AxisY.Minimum = 0;		Chart1.ChartAreas["ChartArea1"].AxisY.Maximum = TotalMemory;		Chart1.ChartAreas["ChartArea1"].AxisY.LabelStyle.Format = "f2";  // 只显示2位小数		Chart1.DataBind();	}	protected void Disk_Chart_Load()	{		for (int i = 0; i < DiskData.Length; i++)		{			string name = DiskData[i].Name;			float used = (DiskData[i].Size - DiskData[i].Free) / GBFactor;			float free = DiskData[i].Free / GBFactor;			float size = DiskData[i].Size / GBFactor;			List<string> dataN = new List<string>();			List<string> dataS = new List<string>();			dataN.Add("可用空间");			dataN.Add("已用空间");			dataS.Add(free.ToString("f2"));			dataS.Add(used.ToString("f2"));			#region 动态添加表			Chart m_chart = new Chart();			m_chart.Width = 500;			m_chart.Height = 400;			ChartArea m_area;			Series m_series;			m_area = new ChartArea("ChartArea" + i.ToString());			m_series = new Series("Series" + i.ToString());			m_chart.ChartAreas.Add(m_area);			m_chart.Series.Add(m_series);			Legend m_legend = new Legend("Legend" + i.ToString());			m_legend.Docking = Docking.Top;			m_legend.LegendStyle = LegendStyle.Row;			m_chart.Legends.Add(m_legend);			Title m_title = new Title("磁盘驱动器" + name);			m_title.Font = new System.Drawing.Font("微软雅黑", 16);			m_title.ForeColor = System.Drawing.Color.SteelBlue;			m_chart.Titles.Add(m_title);			m_series.ChartType = SeriesChartType.Pie;  // 饼图			m_series.ChartArea = m_area.Name;			m_series.LegendText = "#VALX: #VALY GB";			m_series.Label = "#VALY GB [#PERCENT]";			m_series.Points.DataBindXY(dataN, dataS);			m_series["PieLabelStyle"] = "Outside";  //饼图说明显示方式(外面)			m_series.ShadowOffset = 2;			m_series.BorderColor = System.Drawing.Color.DarkGray;			#endregion			StaticPanel.Controls.Add(m_chart);		}	}	protected void Net_Chart_Load()	{		DataTable m_dt = new DataTable();		m_dt.Columns.Add("时间", typeof(int));		m_dt.Columns.Add("上传速率 (KB/s)", typeof(float));		m_dt.Columns.Add("下载速率 (KB/s)", typeof(float));		m_dt.Columns.Add("最大速率 (KB/s)", typeof(float));		DataLoad2(ref m_dt);		Chart1.DataSource = m_dt;		Chart1.Series["Series1"].XValueMember = "时间";		Chart1.Series["Series1"].YValueMembers = "下载速率 (KB/s)";		float downLoadRate = NetData[NetData.Count - 1].Received / (m_timeInterval * KBFactor);		Chart1.Series["Series1"].LegendText = "下载速率:" + downLoadRate.ToString("f2") + " KB/s";		Series m_series = new Series("Series2");		m_series.XValueMember = "时间";		m_series.YValueMembers = "上传速率 (KB/s)";		m_series.ChartType = SeriesChartType.SplineArea;		m_series.Color = System.Drawing.Color.FromArgb(128, System.Drawing.Color.LightGreen);  // 半透明,防止互相遮挡		m_series.BorderColor = System.Drawing.Color.Green;		Chart1.Series.Add(m_series);				float upLoadRate = NetData[NetData.Count - 1].Sent / (m_timeInterval * KBFactor);		Chart1.Series["Series2"].LegendText = "上传速率:" + upLoadRate.ToString("f2") + " KB/s";		Chart1.Legends["Legend1"].Enabled = true;		Chart1.ChartAreas["ChartArea1"].AxisY.Title = "上传下载速率 (KB/s)";		Chart1.DataBind();	}}

最后这个aspx.cs文件做了些修改,可能会导致编译无法通过,如果直接复制过去的话,需要自己修改一下。另外有几个地方时间紧来不及好好设计实现了,凑合完成了功能,有时间可以再好好弄一下。比如网络可以根据当前传输速率自动切换单位为MB和KB什么的。

 

最后上个图

广告 广告

评论区