程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 進程監視類ProceWatcher

進程監視類ProceWatcher

編輯:C#入門知識

/*========================================================
 * 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的專欄
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved