最近一直忙一个专案,是做一个程式监控系统,这个系统其实没有什么,就是要达到在网络上去控制公司其他的程式,主要包括更新程式文件,上传文件,查看运行状态,编辑监控程式的配置文件,开启关闭预约重起目标电脑,下载log档案,在线查看操作日志。
这个系统设计主要分三层架构设计,一个是目标机器中的管理程式,一个是放置于中间网络的传输程式,一个是用来查看并操作的客户端,其中中间程式可以由1个到n个,这个就方便了扩展,因为程式不是在一个地方运行,可能在很多地方运行很多。
在这个系统中重点我想应该有这么几个
1.是网络传输,定义一套用来传输的协议格式,使用tcp的方式进行连接,同时确保tcp连接的有效性,即需要有自动重连接机制以及其他的安全机制。
2.程式的运行状态的获取,这个获取包括获取很多信息,包括程式的图标,CPU,Memory, ThreadCount,Handle等...
3.程式文件的更新上传等操作,这个部分我想应该归纳到网络传输的部分。
其实功能上看没有什么,但是要把这些组织起来并且生成一个系统统一管理还是挺麻烦的,因为监控端很多,并且每个监控端都要监控很多程式,还要保证监控端不能过多的使用CPU等资源。网络传递大文件时的传输机制...等等,反正烦的事有好多,不过还好现在已经基本完成了。
现在把我做这个系统是涉及到的一些小知识点记录下来,以便以后使用。
下面开始了
一.程序运行状态的获取,包括CPU利用率,内存使用情况,线程个数等信息。
运行状态的获取我使用的方法是使用性能计数器组件,PerformanceCounter。
首先定义一些计数器,如下:
#region ForProcessFun
PerformanceCounter pcCPU ;
PerformanceCounter pcMemory ;
PerformanceCounter pcVMemory;
PerformanceCounter pcMemoryPeak;
PerformanceCounter pcHandle;
PerformanceCounter pcThread;
PerformanceCounter pcID;
PerformanceCounter pTimes;
#endregion
#region ForProcess
public const string ProcessObject = "Process";
public const string CPUPerS = "% Processor Time";
public const string MemoryS = "Working Set";
public const string MemoryPeakS = "Working Set Peak";
public const string VMemoryS = "Private Bytes";
public const string VMemoryPeekS = "";
public const string HandleS = "Handle Count";
public const string ThreadS = "Thread Count";
public const string IDS = "ID Process";
public const string ElapsedTimes = "Elapsed Time";
public const string ProcessorObject = "Processor";
public const string TotalS ="_Total";
#endregion
调用方法如下:
pcCPU = new PerformanceCounter(ProcessObject,CPUPerS,this._ExeName);
pinfo.CPU = ((int)pcCPU.NextValue()).ToString() + " %";
pcMemory = new PerformanceCounter(ProcessObject,MemoryS,this._ExeName);
pinfo.Memory = Common.Adddouhao((pcMemory.NextValue() /1024).ToString()) + " k";
pcVMemory = new PerformanceCounter(ProcessObject,VMemoryS,this._ExeName);
pinfo.VMemory = Common.Adddouhao((pcVMemory.NextValue() /1024).ToString()) + " k";
pcMemoryPeak = new PerformanceCounter(ProcessObject,MemoryPeakS,this._ExeName);
pinfo.MemoryPeek = Common.Adddouhao((pcMemoryPeak.NextValue() /1024).ToString()) + " k";
pcHandle = new PerformanceCounter(ProcessObject,HandleS,this._ExeName);
pinfo.Handle = pcHandle.NextValue().ToString();
pcThread = new PerformanceCounter(ProcessObject,ThreadS,this._ExeName);
pinfo.ThreadCount = pcThread.NextValue().ToString();
其实很简单,就是定义一个性能计数器,然后获取值。其中_ExeName是在进程管理器中的名称。
因为这个地方我是通过路径名去获取这个程式在进程中的名称,但是在进程管理器中显示的名称有时会显示短名称(不知道是不是这么这叫,就是不是exe的名称了,变成有^的那在种了),如果变名了就获取不到它的运行值了。
可以使用API把长路径和短路径进行转换,API的定义如下:
[DllImport("kernel32.dll",CharSet = CharSet.Auto)]
public static extern int GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string path,
[MarshalAs(UnmanagedType.LPTStr)]
System.Text.StringBuilder shortPath,
int shortPathLength);
[DllImport("kernel32.dll",CharSet = CharSet.Auto)]
public static extern int GetLongPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string path,
[MarshalAs(UnmanagedType.LPTStr)]
System.Text.StringBuilder shortPath,
int shortPathLength);
调用方法:
变成短路径:
System.Text.StringBuilder shortname = new System.Text.StringBuilder(128);
Common.GetShortPathName(this.AppPath,shortname,128);
_ExeName = System.IO.Path.GetFileNameWithoutExtension(shortname.ToString());
使用WMI获取运行的状态,这个方法是开始设计的时候打算使用的方法,但是后来取消这个方法了全部使用上面的方法,不过这里也说一下.
代码片断:
public void GetProcessAll()
{
try
{
SelectQuery query=new SelectQuery("Select * From Win32_PerfFormattedData_PerfProc_Process");
ManagementObjectSearcher searcher=new ManagementObjectSearcher(query);
this.ProcessAllTable.count = 0;
ManagementObjectCollection coll = searcher.Get();
this.ProcessAllTable.count = coll.Count;
this.ProcessAllTable.table = new Win32_PerfFormattedData_PerfProc_Process[this.ProcessAllTable.count];
int i = 0;
foreach(ManagementBaseObject p in coll)
{
Win32_PerfFormattedData_PerfProc_Process po = new Win32_PerfFormattedData_PerfProc_Process();
po.Caption = p["Caption"]==null?"":p["Caption"].ToString();
po.CreatingProcessID = p["CreatingProcessID"]==null?"":p["CreatingProcessID"].ToString();
po.Description = p["Description"]==null?"":p["Description"].ToString();
po.ElapsedTime = p["ElapsedTime"]==null?"":p["ElapsedTime"].ToString();
po.Frequency_Object = p["Frequency_Object"]==null?"":p["Frequency_Object"].ToString();
po.Frequency_PerfTime = p["Frequency_PerfTime"]==null?"":p["Frequency_PerfTime"].ToString();
po.Frequency_Sys100NS = p["Frequency_Sys100NS"]==null?"":p["Frequency_Sys100NS"].ToString();
po.HandleCount = p["HandleCount"]==null?"":p["HandleCount"].ToString();
po.IDProcess = p["IDProcess"]==null?"":p["IDProcess"].ToString();
po.IODataBytesPerSec = p["IODataBytesPerSec"]==null?"":p["IODataBytesPerSec"].ToString();
po.IODataOperationsPerSec = p["IODataOperationsPerSec"]==null?"":p["IODataOperationsPerSec"].ToString();
po.IOOtherBytesPerSec = p["IOOtherBytesPerSec"]==null?"":p["IOOtherBytesPerSec"].ToString();
po.IOOtherOperationsPerSec = p["IOOtherOperationsPerSec"]==null?"":p["IOOtherOperationsPerSec"].ToString();
po.IOReadBytesPerSec = p["IOReadBytesPerSec"]==null?"":p["IOReadBytesPerSec"].ToString();
po.IOReadOperationsPerSec = p["IOReadOperationsPerSec"]==null?"":p["IOReadOperationsPerSec"].ToString();
po.IOWriteBytesPerSec = p["IOWriteBytesPerSec"]==null?"":p["IOWriteBytesPerSec"].ToString();
po.IOWriteOperationsPerSec = p["IOWriteOperationsPerSec"]==null?"":p["IOWriteOperationsPerSec"].ToString();
po.Name = p["Name"]==null?"":p["Name"].ToString();
po.PageFaultsPerSec = p["PageFaultsPerSec"]==null?"":p["PageFaultsPerSec"].ToString();
po.PageFileBytes = p["PageFileBytes"]==null?"":p["PageFileBytes"].ToString();
po.PageFileBytesPeak = p["PageFileBytesPeak"]==null?"":p["PageFileBytesPeak"].ToString();
po.PercentPrivilegedTime = p["PercentPrivilegedTime"]==null?"":p["PercentPrivilegedTime"].ToString();
po.PercentProcessorTime = p["PercentProcessorTime"]==null?"":p["PercentProcessorTime"].ToString();
po.PercentUserTime = p["PercentUserTime"]==null?"":p["PercentUserTime"].ToString();
po.PoolNonpagedBytes = p["PoolNonpagedBytes"]==null?"":p["PoolNonpagedBytes"].ToString();
po.PoolPagedBytes = p["PoolPagedBytes"]==null?"":p["PoolPagedBytes"].ToString();
po.PriorityBase = p["PriorityBase"]==null?"":p["PriorityBase"].ToString();
po.PrivateBytes = p["PrivateBytes"]==null?"":p["PrivateBytes"].ToString();
po.ThreadCount = p["ThreadCount"]==null?"":p["ThreadCount"].ToString();
po.Timestamp_Object = p["Timestamp_Object"]==null?"":p["Timestamp_Object"].ToString();
po.Timestamp_PerfTime = p["Timestamp_PerfTime"]==null?"":p["Timestamp_PerfTime"].ToString();
po.Timestamp_Sys100NS = p["Timestamp_Sys100NS"]==null?"":p["Timestamp_Sys100NS"].ToString();
po.VirtualBytes = p["VirtualBytes"]==null?"":p["VirtualBytes"].ToString();
po.VirtualBytesPeak = p["VirtualBytesPeak"]==null?"":p["VirtualBytesPeak"].ToString();
po.WorkingSet = p["WorkingSet"]==null?"":p["WorkingSet"].ToString();
po.WorkingSetPeak = p["WorkingSetPeak"]==null?"":p["WorkingSetPeak"].ToString();
this.ProcessAllTable.table[i] = po;
i++;
}
}
catch(System.Exception exp)
{
string s = exp.Message;
this.ProcessAllTable.count = 0;
}
}
其中Win32_PerfFormattedData_PerfProc_Process 为一个自己定义的类,定义如下:
public class Win32_PerfFormattedData_PerfProc_Process
{
public string Caption= "";
public string CreatingProcessID= "";//指创建的处理的处理 Process ID。创建进程可能已终止,这个值可能已 经不在识别一个运行的处理。
public string Description= "";
public string ElapsedTime= "";//这个处理运行的总时间(用秒计算)
public string Frequency_Object= "";
public string Frequency_PerfTime= "";
public string Frequency_Sys100NS= "";
public string HandleCount= "";
public string IDProcess= "";//ID Process 指这个处理的特别的识别符。ID Process 号可重复使用,所以这些 ID Process 号只能在一个处理的寿命期内识别那个处理。
public string IODataBytesPerSec= "";//处理从 I/O 操作读取/写入字节的速度。这个计数器为所有由本处理产生的包括文件、网络和设备 I/O 的活动计数。
public string IODataOperationsPerSec= "";
public string IOOtherBytesPerSec= "";
public string IOOtherOperationsPerSec= "";
public string IOReadBytesPerSec= "";
public string IOReadOperationsPerSec= "";
public string IOWriteBytesPerSec= "";
public string IOWriteOperationsPerSec= "";
public string Name= "";
public string PageFaultsPerSec= "";
public string PageFileBytes= "";
public string PageFileBytesPeak= "";
public string PercentPrivilegedTime= "";
public string PercentProcessorTime= "";//cpu利用率
public string PercentUserTime= "";
public string PoolNonpagedBytes= "";
public string PoolPagedBytes= "";
public string PriorityBase= "";
public string PrivateBytes= "";
public string ThreadCount= "";
public string Timestamp_Object= "";
public string Timestamp_PerfTime= "";
public string Timestamp_Sys100NS= "";
public string VirtualBytes= "";//虚拟地址空间的以字节数
public string VirtualBytesPeak= "";
public string WorkingSet= "";//Working Set 指这个处理的 Working Set 中的当前字节数。
public string WorkingSetPeak= "";// Working Set 的最大字节数
}
上面的方法只是获取进程的一些信息,如果要获取OS的信息或其他信息可以参考MSDN中对WMI的描述在改一个如上的。不过.net中好像有关于WMI的类。不过我没有去找过。有兴趣的朋友可以查一下看看。
获取硬盘信息的WMI处理方法:
SelectQuery query=new SelectQuery("Select * From Win32_LogicalDisk where DriveType=3");
ManagementObjectSearcher searcher=new ManagementObjectSearcher(query);
System.Management.ManagementObjectCollection moc = searcher.Get();
int count = moc.Count;
einfo.DiskName = new string[count];
einfo.DiskTotalSize = new string[count];
einfo.DiskFreeSize = new string[count];
int i = 0;
foreach(ManagementBaseObject disk in searcher.Get())
{
if(disk["VolumeName"].ToString() == "")
{
einfo.DiskName[i] = disk["Name"].ToString();
}
else
{
einfo.DiskName[i] = disk["Name"].ToString() + "[" + disk["VolumeName"].ToString() + "]";
}
einfo.DiskTotalSize[i] = disk["Size"].ToString();
einfo.DiskFreeSize[i] = disk["FreeSpace"].ToString();
i++;
Console.WriteLine("\r\n"+disk["Name"] +" "+disk["DriveType"] + " " + disk["VolumeName"]);
}
二.获取程序的icon及设定的日志文件程式文件列表。
获取ICON我使用的是API获取,因为这个方法获取到程式的ICON效果不是很好,但是在我这个系统中这个方法也可以了。要获取更清晰的ICON我也不知道,要是哪位高手知道希望也告诉我一下,这里先谢谢了。
获取ICON的类:也是在网络上找到的。
public class CIcon
{
private const UInt32 SHGFI_ICON = 0x100;
private const UInt32 SHGFI_LARGEICON = 0x0; // 'Large icon
private const UInt32 SHGFI_SMALLICON = 0x1; // 'Small icon
[DllImport("shell32.dll")]
private static extern IntPtr SHGetFileInfo(string pszPath,
UInt32 dwFileAttributes, ref SHFILEINFO psfi, UInt32 cbSizeFileInfo,
UInt32 uFlags);
[StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
public IntPtr hIcon;
public IntPtr iIcon;
public UInt32 dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
public static System.Drawing.Icon GetIcon(string filename,bool
b_large_icon)
{
UInt32 icon_size;
if (b_large_icon)
icon_size=SHGFI_LARGEICON;
else
icon_size=SHGFI_SMALLICON;
IntPtr hImgSmall;
SHFILEINFO shinfo = new SHFILEINFO();
hImgSmall = SHGetFileInfo(filename, 0, ref
shinfo,(UInt32)Marshal.SizeOf(shinfo),SHGFI_ICON |icon_size);
System.Drawing.Icon myIcon =
System.Drawing.Icon.FromHandle(shinfo.hIcon);
return myIcon;
}
}
文件列表的获取方法就不说了,其实就是遍历获取需要的文件。
今天先写这些吧...