home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2005 June (DVD) / DPPRO0605DVD.iso / Install / program files / Borland / BDS / 3.0 / Demos / CSharp / Applications / Process View / ProcessChecker.cs < prev    next >
Encoding:
Text File  |  2004-10-22  |  8.0 KB  |  247 lines

  1. /*******************************************************************************
  2.   ProcessChecker Demo
  3.   Example submitted by David Clegg
  4.  
  5.   This unit contains the ProcessChecker class, which is responsible for
  6.   monitoring, stopping and restarting processes.
  7. *******************************************************************************/
  8. using System;
  9. using System.IO;
  10. using System.Windows.Forms;
  11. using System.Threading;
  12. using System.Diagnostics;
  13.  
  14. namespace ProcessChecker {
  15.  
  16.     //Delegate for Process Checker Event notification
  17.     public delegate void ProcessCheckerEventNotify(object sender, ProcessCheckerEventArgs args);
  18.  
  19.     /// <summary>
  20.     /// Derived EventArgs class used by ProcessCheckerEventNotify delegate
  21.     /// </summary>
  22.     public class ProcessCheckerEventArgs : EventArgs {
  23.         string fMessage;
  24.         public ProcessCheckerEventArgs(string message) {
  25.             fMessage = message;
  26.         }
  27.  
  28.         public string Message {
  29.             get{return fMessage;}
  30.         }
  31.     }
  32.  
  33.     /// <summary>
  34.     /// Class to handle the Process monitoring. As I become more
  35.     /// preficient, I will host this in a seperate thread.
  36.     /// </summary>
  37.     public class ProcessChecker {
  38.         private ProcessCheckerSettings fSettings;
  39.         private bool fSuspended = false;
  40.         private System.Windows.Forms.Timer timCheck;
  41.  
  42.         public ProcessChecker(ProcessCheckerSettings settings) {
  43.             fSettings = settings;
  44.             InitTimer();
  45.             InitSettings();
  46.         }
  47.  
  48.         public event ProcessCheckerEventNotify ProcessCheckerEvent;
  49.  
  50.         /// <summary>
  51.         /// Returns a reference to the ProcessCheckerSettings instance.
  52.         /// </summary>
  53.         public ProcessCheckerSettings Settings {
  54.             get {return fSettings;}
  55.         }
  56.  
  57.         /// <summary>
  58.         /// Temporarily suspends process checking without affecting the
  59.         /// ProcessCheckerSettings.Enabled property.
  60.         /// </summary>
  61.         public void Suspend() {
  62.             fSuspended = true;
  63.         }
  64.  
  65.         /// <summary>
  66.         /// Resumes process checking, if it was suspended.
  67.         /// </summary>
  68.         public void Resume() {
  69.             fSuspended = false;
  70.         }
  71.  
  72.         /// <summary>
  73.         /// Create the timer, and attach the Tick event.
  74.         /// </summary>
  75.         private void InitTimer() {
  76.             //There is a Timer class in System.Threading and System.Windows.Forms.
  77.             //As this is a simple single-threaded implementation, for now we
  78.             //will use the WinForms one.
  79.             timCheck = new System.Windows.Forms.Timer();
  80.             timCheck.Tick += new EventHandler(timCheck_Tick);
  81.             SetTimerInterval();
  82.         }
  83.  
  84.         /// <summary>
  85.         /// Create the ProcessCheckerSettings instance, and attach the event
  86.         /// handlers to notify when the instance is loaded or saved.
  87.         /// </summary>
  88.         private void InitSettings() {
  89.             fSettings.SettingsLoaded += new EventHandler(Settings_Updated);
  90.             fSettings.SettingsSaved += new EventHandler(Settings_Updated);
  91.  
  92.             //As the event handlers are attached after the settings are
  93.             //initially loaded from disk, we need to fire the event manually.
  94.             Settings_Updated(this, null);
  95.         }
  96.  
  97.         /// <summary>
  98.         /// Event handler called if the ProcessCheckerSettings instance is loaded
  99.         /// or saved. As we are only interested in determining that the settings
  100.         /// may have changed (and not what caused the change), we can share the
  101.         /// event handler.
  102.         /// </summary)
  103.         private void Settings_Updated(object sender, EventArgs args) {
  104.             SetTimerInterval();
  105.         }
  106.  
  107.         /// <summary>
  108.         /// Sets the interval for the timer used to trigger the process checking
  109.         /// </summary>
  110.         private void SetTimerInterval() {
  111.             //CheckFrequency is stored in seconds, but we need to convert it
  112.             //to milliseconds for the timer.
  113.             int lInterval = fSettings.CheckFrequency * 1000;
  114.  
  115.             //Timer class will throw an exception if we attempt to assign an
  116.             //interval with a zero value
  117.             if (lInterval > 0) {
  118.                 timCheck.Interval = lInterval;
  119.                 timCheck.Enabled = fSettings.Enabled;
  120.             }
  121.             else {
  122.                 //Ensure timer is disabled
  123.                 timCheck.Enabled = false;
  124.                 fSettings.Enabled = false;
  125.                 fSettings.Save();
  126.             }
  127.         }
  128.  
  129.         private void timCheck_Tick(object sender, System.EventArgs e) {
  130.             CheckProcesses();
  131.         }
  132.  
  133.         /// <summary>
  134.         /// Iterate through all monitored processes to check whether they are
  135.         /// still running.
  136.         /// </summary>
  137.         private void CheckProcesses() {
  138.             Process[] processes;
  139.             if (fSuspended != true)
  140.                 foreach (WatchedProcess watchedProcess in fSettings.WatchedProcesses)
  141.                 {
  142.                     processes = CheckProcess(watchedProcess.ProcessPath);
  143.                     if (processes.Length == 0) {
  144.                         //No instances of watchedProcess running, so re-start it
  145.                         RestartProcess(watchedProcess);
  146.                         if (fSettings.RestartOneProcess)
  147.                             //We only restart one process each time we check
  148.                             //running processes. Any subsequent processes that have
  149.                             //unexpectedly terminated will be caught next time.
  150.                             break;
  151.                     }
  152.                     else
  153.                         foreach (Process runningProcess in processes)
  154.                             //At least one instance of watchedProcess running,
  155.                             //so check that the instance(s) are still responding.
  156.                             if (watchedProcess.CheckResponding)
  157.                                 if (runningProcess.Responding == false) {
  158.                                     //Process not responding, so re-start it.
  159.                                     NotifyEvent(string.Format("{0} - not responding",
  160.                                                               runningProcess.ProcessName));
  161.                                     StopProcess(runningProcess);
  162.                                     RestartProcess(watchedProcess);
  163.                                     if (fSettings.RestartOneProcess)
  164.                                         //Only restarting one process per check.
  165.                                         break;
  166.                                 }
  167.                 }
  168.         }
  169.  
  170.         /// <summary>
  171.         /// Check to see whether the specified process is still running.
  172.         /// Returns an array of Process instances if the process has at least one
  173.         /// running instance.
  174.         /// </summary>
  175.         public Process[] CheckProcess(string processPath) {
  176.             string lProcessName = Path.GetFileNameWithoutExtension(processPath);
  177.             return Process.GetProcessesByName(lProcessName);
  178.         }
  179.  
  180.         /// <summary>
  181.         /// Restart a process.
  182.         /// </summary>
  183.         private void RestartProcess(WatchedProcess process) {
  184.             StopDependantProcesses(process);
  185.             Process startProcess = new Process();
  186.             startProcess.StartInfo.FileName = process.ProcessPath;
  187.             startProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(process.ProcessPath);
  188.             try {
  189.                 startProcess.Start();
  190.                 NotifyEvent(string.Format("{0} - Process restarted", process.ProcessName));
  191.             }
  192.             catch (Exception exception) {
  193.                 NotifyEvent(string.Format("Error starting {0} - {1}",
  194.                                            process.ProcessName, exception.Message));
  195.             }
  196.         }
  197.  
  198.         /// <summary>
  199.         /// Iterate through, and terminate, all dependant processes.
  200.         /// </summary>
  201.         private void StopDependantProcesses(WatchedProcess process) {
  202.             Process[] dependantProcesses;
  203.             foreach(ProcessDetails dependantDetails in process.DependantProcesses) {
  204.                 dependantProcesses = CheckProcess(dependantDetails.ProcessPath);
  205.                 foreach (Process dependant in dependantProcesses)
  206.                     StopProcess(dependant);
  207.             }
  208.         }
  209.  
  210.         /// <summary>
  211.         /// Stop a process.
  212.         /// </summary>
  213.         private void StopProcess(Process process) {
  214.             //Attempt to stop the process 'nicely' by sending a Close message
  215.             //to the processes main window
  216.             process.CloseMainWindow();
  217.             //Give the message a chance to be processed
  218.             Thread.Sleep(100);
  219.             if (process.HasExited == false) {
  220.                 //CloseMainWindow didn't work so attempt a more forceful
  221.                 //shutdown. Process.Kill forces an immediate termination of the
  222.                 //process.
  223.                 process.Kill();
  224.                 Thread.Sleep(100);
  225.                 if (process.HasExited == false)
  226.                     //Still running, but its time to admit defeat :-(
  227.                     NotifyEvent(string.Format("{0} - Process termination failed",
  228.                                 process.ProcessName));
  229.                 else
  230.                     NotifyEvent(string.Format("{0} - Process killed",
  231.                                 process.ProcessName));
  232.             }
  233.             else
  234.                 NotifyEvent(string.Format("{0} - Process stopped",
  235.                             process.ProcessName));
  236.         }
  237.  
  238.         /// <summary>
  239.         /// Send a Process Checker Event notification.
  240.         /// </summary>
  241.         private void NotifyEvent(string eventDetails) {
  242.             ProcessCheckerEventArgs args = new ProcessCheckerEventArgs(eventDetails);
  243.             ProcessCheckerEvent(this, args);
  244.         }
  245.     }
  246. }
  247.