• .NET基础示例系列之十六:制做进程监视器


    1)可以查看进程的各项基本信息,如cpu,内存,父进程,执行路径,创建者等

    2)可以中止进程,创建新进程

    3)可以配置目标进程,配置刷新速度

    最终效果图:

    (以下给出部分代码,其余像进程的创建、中止等,使用process类将很容易实现)

    1)使用wmi获取父进程id,进程创建者

    (注意,使用wmi获得的内容,不宜循环刷新,这样代价比较大)

    添加命名空间:

    using System.Management;

     


            
    /// <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>
        
    /// 该类用于监测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;
                }

            }

        }


     

     

    2)使用性能计数器计算cpu利用率

    2.1)计算过程

    //通过计数器获取idle空闲进程cpu占用率r1

    //通过process类的TotalProcessorTime属性获取各进程的cpu时间,求和,得各进程(除空闲进程idle,该进程无法通过process类获得cpu时间)cpu时间和t1

    //通过t1/(100-r1)得到总cpu时间t

    //对各进程,通过TotalProcessorTime获得进程cpu时间tnew,计算:

    (Tnew-told)/t,即得该进程的cpu占用率,其中told是程序中记录的该进程上一次的TotalProcessorTime

     

    2.2)关于性能计数器

    系统会为每个进程分配一个计数器,通过

    new PerformanceCounter("Process", "% Processor Time", "进程名称")实例化该计数器,使用计数器对象的NextValue方法可以得到进程占用cpu的百分比(第一次调用NextValue获取的值都为0,之后就没问题了,这个要注意)。

     

    2.3)Idle进程的含义

    Idle意为懒散的、无所事事。事实上,idle不能算着一个进程,它用于表示cpu空闲资源,它所占的比率越高,表示你的机器越空闲。

     

    2.4)多核CPU或使用超线程技术的CPU

    对于多核或使用超线程技术的cpu,根据计数器求得的idle进程cpu占用比率将超过100%,此时应将idlecpu利用率/总的cpu利用率,所得作为真正的idlecpu利用率。

     

    添加命名空间:

    using System.Diagnostics;


            
    /// <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 void FillNeedRefreshInfo(params Process[] pCurrentAll)
            
    {
                …………
                
    //以下计算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
                        
    {
                            
    //无法保证进程不会中途退出,此时无法获取其Cpu时间
                            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);
                    }

                }

            }



            
    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);
            }


      代码下载

  • 相关阅读:
    关于dubbo创建服务和引用服务时,会报错:cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 问题的解决
    解决 Maven工程运行报错Failed to clean project: Failed to delete
    Linux学习_004_使用CentOS 7.5卸载自带jdk安装自己的JDK1.8
    Linux下的JDK和OpenJDK有什么具体的区别
    常用的大数据技术有哪些?
    如何隐藏你的 Linux 的命令行历史
    Securi-Pi:使用树莓派作为安全跳板
    在 Linux 上管理加密密钥的最佳体验
    在 Linux 下使用任务管理器
    在 Linux 中安装 Lighttpd Web 服务器
  • 原文地址:https://www.cnblogs.com/morvenhuang/p/681739.html
Copyright © 2020-2023  润新知