/*========================================================
* Author:myhuang
* Date:2007-02-26
* Note:獲取進程主要屬性值
========================================================*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Management;
namespace ProceWatcher
{
/// <summary>
/// 進程類
/// </summary>
public class MyProcess
{
/// <summary>
/// 進程ID
/// </summary>
public int ProceID;
/// <summary>
/// 進程名稱
/// </summary>
public string ProceName;
/// <summary>
/// 執行路徑
/// </summary>
public string ExecPath;
/// <summary>
/// 創建者
/// </summary>
public string Creator;
/// <summary>
/// 創建時間
/// </summary>
public string CreateTime;
/// <summary>
/// 線程數
/// </summary>
public int ThreadsCount;
/// <summary>
/// CPU占用率
/// </summary>
public double CpuPercent;
/// <summary>
/// 上次CPU時間
/// </summary>
public long OldCpuTime;
/// <summary>
/// 物理內存(KB)
/// </summary>
public long MemoryKB;
/// <summary>
/// 虛擬內存(KB)
/// </summary>
public long VirtualKB;
/// <summary>
/// 父進程名
/// </summary>
public string ParentProce;
/// <summary>
/// 公司信息
/// </summary>
public string CompanyName;
/// <summary>
/// 是否是目標進程
/// </summary>
public bool Target;
/// <summary>
/// 是否活動
/// </summary>
public bool Active;
}
#region 委 托
public delegate void DlgProceNew(MyProcess pProce);
public delegate void DlgProceClosed(MyProcess pProce);
public delegate void DlgProceRefresh(MyProcess pProce,double pCpuPercent);
public delegate void DlgDetailList(MyProcess pProce);
#endregion
/// <summary>
/// 該類提供獲取進程信息的功能
/// </summary>
public class ProcessInfo
{
#region 私有成員
/// <summary>
/// 字典類,用於保存各進程信息
/// </summary>
private Dictionary<int, MyProcess> mDict;
/// <summary>
/// 當前總CPU時間
/// </summary>
private double mCurrentTotalCpuTime;
/// <summary>
/// CPU空閒比率
/// </summary>
private double mIdleCpuPercent;
/// <summary>
/// 當前進程
/// </summary>
private Process[] mCurrentAll;
/// <summary>
/// 性能計數器,用於獲取CPU空閒百分比
/// </summary>
private static PerformanceCounter mIdle = new PerformanceCounter("Process", "% Processor Time", "Idle");
/// <summary>
/// 性能計數器,用於獲取CPU總利用率
/// </summary>
private static PerformanceCounter mTotal = new PerformanceCounter("Process", "% Processor Time", "_Total");
private object mLock = new object();
#endregion
#region 事 件
/// <summary>
/// 當出現新進程時觸發該事件
/// </summary>
public event DlgProceNew HandleProceNew;
/// <summary>
/// 當進程關閉時觸發該事件
/// </summary>
public event DlgProceClosed HandleProceClosed;
/// <summary>
/// 當進程信息更新時觸發該事件
/// </summary>
public event DlgProceRefresh HandleProceRefresh;
/// <summary>
/// 當獲取進程詳細信息時觸發該事件
/// </summary>
public event DlgDetailList HandleDetailList;
#endregion
/// <summary>
/// 構造器 www.2cto.com
/// </summary>
public ProcessInfo()
{
}
/// <summary>
/// 提供刷新進程列表的功能
/// </summary>
/// <param name="pReLoadAll">是否強制完全重新加載</param>
public void RefreshProceList(bool pReLoadAll)
{
//當前進程列表
this.mCurrentAll = Process.GetProcesses();
#region 初始化或重新加載
if (this.mDict ==null || pReLoadAll)
{
//初始化字典類
this.mDict = new Dictionary<int, MyProcess>();
//獲取基本信息
this.FillBaseInfo(this.mCurrentAll);
//獲取需要更新的信息
this.FillNeedRefreshInfo(this.mCurrentAll);
return;
}
#endregion
#region 進程關閉處理
//使用lock避免多線程造成mDict不一致(?)
lock (this.mLock)
{
//foreach枚舉時不能刪除原集合元素,記錄相應的key,循環完成之後再刪除
List<int> list = new List<int>();
foreach (KeyValuePair<int, MyProcess> kvp in this.mDict)
{
if (this.ProceClosedInDict(kvp.Key))
{
list.Add(kvp.Key);
}
}
MyProcess mp = null;
foreach (int id in list)
{
if (this.mDict.ContainsKey(id))
{
mp = this.mDict[id];
this.mDict.Remove(id);
//觸發進程關閉事件
if (this.HandleProceClosed != null)
{
this.HandleProceClosed(mp);
}
}
}
}
#endregion
#region 進程信息刷新(包括新增)
for (int i = 0; i < this.mCurrentAll.Length; i++)
{
//新增進程
if (!this.mDict.ContainsKey(this.mCurrentAll[i].Id))
{
this.FillBaseInfo(this.mCurrentAll[i]);
}
}
this.FillNeedRefreshInfo(this.mCurrentAll);
#endregion
}
/// <summary>
/// 提供刷新進程其它詳細信息的功能
/// </summary>
/// <param name="pID">進程ID</param>
public void RefreshDetailList(int pID)
{
this.FillDetailUseWmi(pID);
}
/// <summary>
/// 獲取指定進程集合中各進程的基本信息
/// </summary>
/// <param name="pCurrentAll"></param>
private void FillBaseInfo(params Process[] pCurrentAll)
{
MyProcess mp = null;
for (int i = 0; i < pCurrentAll.Length; i++)
{
//判斷在循環中途,是否有某一進程退出
if (this.ProceClosedInCurrentList(pCurrentAll[i]))
{
return;
}
mp = new MyProcess();
mp.ProceID = pCurrentAll[i].Id;
mp.ProceName = pCurrentAll[i].ProcessName;
try
{
//對於空閒進程idle等,無法獲取其主模塊文件名
mp.ExecPath = pCurrentAll[i].MainModule.FileName.ToLower();//
mp.CreateTime = pCurrentAll[i].StartTime.ToString();
mp.CompanyName = pCurrentAll[i].MainModule.FileVersionInfo.CompanyName;
}
catch
{
}
//根據執行文件路徑,判斷進程是否為目標進程
if (mp.ExecPath!=null && ConfigMgr.ValueExists(mp.ExecPath))
{
mp.Target = true;
}
//初始化“上一次CPU時間”為0
mp.OldCpuTime = 0;
this.mDict.Add(mp.ProceID, mp);
//觸發新進程事件
if (this.HandleProceNew != null)
{
this.HandleProceNew(mp);
}
}
mp = null;
}
/// <summary>
/// 獲取指定進程集合中各進程需要刷新的信息
/// </summary>
/// <param name="pCurrentAll"></param>
private void FillNeedRefreshInfo(params Process[] pCurrentAll)
{
for (int i = 0; i < pCurrentAll.Length; i++)
{
//判斷在循環中途,是否有某一進程退出,及字典中是否已移除該項(?)
if (this.ProceClosedInCurrentList(pCurrentAll[i]) || !this.mDict.ContainsKey(pCurrentAll[i].Id))
{
return;
}
this.mDict[pCurrentAll[i].Id].MemoryKB = pCurrentAll[i].WorkingSet64 / 1024;
this.mDict[pCurrentAll[i].Id].VirtualKB = pCurrentAll[i].VirtualMemorySize64 / 1024;
this.mDict[pCurrentAll[i].Id].ThreadsCount = pCurrentAll[i].Threads.Count;
}
//以下計算CPU利用率,不放在同一for循環中是為了避免循環時間間隔造成CPU利用率的誤差
this.mCurrentTotalCpuTime = this.CalCurrentTotalCpuTime();
for (int i = 0; i < pCurrentAll.Length; i++)
{
//空閒進程idle
if (pCurrentAll[i].Id == 0)
{
this.mDict[pCurrentAll[i].Id].CpuPercent = this.mIdleCpuPercent;
}
else
{
try
{
//無法保證進程不會中途退出,此時無法獲取其CUP時間
long ms = (long)pCurrentAll[i].TotalProcessorTime.TotalMilliseconds;
double d = (ms - this.mDict[pCurrentAll[i].Id].OldCpuTime) * 1.0 / this.mCurrentTotalCpuTime;
this.mDict[pCurrentAll[i].Id].CpuPercent = d;
this.mDict[pCurrentAll[i].Id].OldCpuTime = ms;
}
catch
{
}
}
//調用刷新事件
if (this.HandleProceRefresh != null)
{
this.HandleProceRefresh(this.mDict[pCurrentAll[i].Id], 100 - this.mIdleCpuPercent);
}
}
}
/// <summary>
/// 使用Wmi獲取指定進程的創建者等信息
/// </summary>
/// <param name="pID">進程ID</param>
private void FillDetailUseWmi(int pID)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ProcessID=" + pID);
ManagementObjectCollection moc = searcher.Get();
ManagementOperationObserver observer = new ManagementOperationObserver();
HandleObjectReady hor = new HandleObjectReady();
//監測異步方法是否已成功返回
observer.ObjectReady += new ObjectReadyEventHandler(hor.Done);
foreach (ManagementObject mo in moc)
{
//異步調用該對象的GetOwner方法,獲取進程創建者
mo.InvokeMethod(observer, "GetOwner", null);
//等待異步調用返回
while (!hor.Complete)
{
System.Threading.Thread.Sleep(500);
}
string user = "";
//判斷獲取用戶名的操作是否成功
if (hor.Obj["returnValue"].ToString() == "0")
{
user = hor.Obj.Properties["User"].Value.ToString();
}
//判斷字典中是否已移除該項
if (!this.mDict.ContainsKey(pID))
{
return;
}
if (mo["ParentProcessID"] != null && this.mDict.ContainsKey(Convert.ToInt32(mo["ParentProcessID"])))
{
//根據父進程ID獲取父進程名稱
this.mDict[pID].ParentProce = this.mDict[Convert.ToInt32(mo["ParentProcessID"])].ProceName;
}
this.mDict[pID].Creator = user;
//觸發刷新進程詳細信息事件
if (this.HandleDetailList != null)
{
this.HandleDetailList(this.mDict[pID]);
}
}
//釋放資源
searcher.Dispose();
searcher = null;
moc.Dispose();
moc = null;
observer = null;
hor = null;
}
/// <summary>
/// 計算當前總CPU時間
/// </summary>
/// <returns></returns>
private double CalCurrentTotalCpuTime()
{
double d = 0;
//獲取性能計數器值
double idlePercent = mIdle.NextValue();
double totalPercent = mTotal.NextValue();
//避免除0異常
if (totalPercent == 0)
{
this.mIdleCpuPercent = 0;
}
else
{
//可能遇到多核或超線程CPU,CPU空閒進程比率不能直接使用計數器的值
this.mIdleCpuPercent = idlePercent * 100 / totalPercent;
}
//以下獲取上一次計算至當前總的非空閒CPU時間
foreach (Process p in this.mCurrentAll)
{
//對空閒進程及中途退出的進程不做處理
if (p.Id == 0 || p.HasExited)
{
continue;
}
if (this.mDict ==null || !this.mDict.ContainsKey(p.Id))
{
d += p.TotalProcessorTime.TotalMilliseconds;
}
else
{
d += p.TotalProcessorTime.TotalMilliseconds - this.mDict[p.Id].OldCpuTime;
}
}
//當前非空閒CPU時間/當前非空閒時間所占比率=當前總CPU時間
//return d / (totalPercent - idlePercent);
return d / (100 - mIdleCpuPercent);
}
/// <summary>
/// 判斷字典中所存的某個進程是否已退出
/// </summary>
/// <param name="pID"></param>
/// <returns></returns>
private bool ProceClosedInDict(int pID)
{
for (int i = 0; i < this.mCurrentAll.Length; i++)
{
if (!this.ProceClosedInCurrentList(this.mCurrentAll[i]) && this.mCurrentAll[i].Id == pID)
{
return false;
}
}
return true;
}
/// <summary>
/// 判斷當前進程列表中的進程是否已中途退出
/// </summary>
/// <param name="pProce"></param>
/// <returns></returns>
private bool ProceClosedInCurrentList(Process pProce)
{
if (pProce.Id == 0)
{
return false;
}
else
{
return pProce.HasExited;
}
}
}
/// <summary>
/// 該類用於監測Wmi異步調用方法是否已經返回
/// </summary>
public class HandleObjectReady
{
private bool complete = false;
private ManagementBaseObject obj;
public void Done(object sender, ObjectReadyEventArgs e)
{
complete = true;
obj = e.NewObject;
}
public bool Complete
{
get
{
return complete;
}
}
public ManagementBaseObject Obj
{
get
{
return obj;
}
}
}
}
摘自 weizhiai12的專欄