公司有个服务进程(C#写的)需要24*7运行,因而希望通过另一个简单的,崩溃几率极低的进程去监控这个服务进程,一旦发现该进程崩溃,就自动重启之。本来希望通过定时获得目前活动进程名称列表的方法来确定那个服务进程是否崩溃,但是实验后发现,进程崩溃时,只要那个"应用程序执行非法操作"的对话框没有关闭,这个进程仍然会存在于进程列表中(即通过任务管理器依然能看到),但此时该进程实际已经崩溃了。因此定时获取进程名称列表的方法实际是无效的~请教各位高手,究竟该如何确定某个进程是否崩溃了?多谢!

解决方案 »

  1.   

    使用WAITFOREXIT进行监控,并在EXITED事件中添加相关的处理
      

  2.   

    使用C#制做进程监视器 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%,此时应将idle的cpu利用率/总的cpu利用率,所得作为真正的idle的cpu利用率。 添加命名空间: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);
            }
      

  3.   

    写一个最简单程序,判断方法如下: public MbMonitor()
    {
    InitializeComponent();

    process=new Process();
    process.StartInfo=new ProcessStartInfo(Directory.GetCurrentDirectory()+"\\"+g_AppName);
    }private void CheckProcessStatus()
    {
    // check two abnormal cases:
    // 1. process has existed somehow
    // 2. process doesn't response this.Cursor=System.Windows.Forms.Cursors.Default;
    if (process.HasExited)
    {
    frm_runStatus.lblStatus.Text = "已退出";
    process.Start();
    }  if(!processBrowser.Responding)
      {
    // close this one
    ShutdownProcess();
    // start a fresh one
    StartProcess();
    }
          
    // everthing looks fine
    } private void ShutdownProcess()
    {
    // first we try to close the browser gracefully,
    // this will assure that the process resources are properly
    // gc'ed
    try
    {
    if (process.HasExited==false)
    {
    if (!process.CloseMainWindow())
    {
    try
    {
    // now the only thing we can do is just kill it
    process.Kill();
    }
    catch (Win32Exception )
    {
    // 0h-o, we can't kill it, now what we do?
    }
    catch (InvalidOperationException )
    {
    // already existed
    }
    catch (SystemException )
    {
    // process doesn't exist?
    }
    }
    }
    }
      

  4.   

    监控程序很简单,就是做一个定时检查,定时调用CheckProcessStatus方法,