C# 實現守護進程


這段時間在做一個關於數據交互的項目。接收到客戶發送過來的文件后,通過Windows服務將文件按一定的規則分發到不同的MQ消息隊列,然后再由不同的處理程序處理。雖然在編碼中盡可能的考慮到了異常以及記錄了詳細的日志,但是服務還是偶爾抽風停掉了,這樣就造成了文件堆積,客戶請求得不到及時的響應。所以需要一個守護進程來保證服務始終是啟動狀態的。

首先,要保證需要監控的進程可配置,以及指定日志的保存位置。在App.config中配置日志保存路徑以及需監控進程和對應的exe可執行程序的位置(之前考慮是如果沒有該服務,則使用exe安裝服務)。

  <appSettings>
    <add key="LogPath" value="D:\Study"/>
    <add key="YTGDataExchangeProcess" value="d:\Study\YTGDataExchangeProcess.exe"/>
  </appSettings>
public class ServiceSearch
    {
        static List<ServiceProcessInfo> _ServiceList = new List<ServiceProcessInfo>();
        static object _logLocker = new Object();
        //日志記錄位置 
        static readonly string _logPath;

        static ServiceSearch()
        {
            try
            {
                string[] appSettingsKeys = ConfigurationManager.AppSettings.AllKeys;

                foreach (string item in appSettingsKeys)
                {
                    string value = ConfigurationManager.AppSettings[item].Trim();
                    //日志配置
                    if (item == "LogPath")
                    {
                        if (!string.IsNullOrEmpty(value))
                        {
                            _logPath = string.Format("{0}\\ProcessMonitorLog", value);
                            if (!Directory.Exists(_logPath))
                            {
                                Directory.CreateDirectory(_logPath);
                            }
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(value))
                        {
                            //應用程序是否存在 
                            if (File.Exists(value))
                            {
                                _ServiceList.Add(new ServiceProcessInfo
                                {
                                    ServiceExePath = value,
                                    ServiceName = item
                                });
                            }
                        }

                    }

                }
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message);
            }
        }

        public static void StartMonitor()
        {
            if (_ServiceList.Count != 0)
            {
                foreach (ServiceProcessInfo info in _ServiceList)
                {
                    string sevName = info.ServiceName;
                    string sevExePath = info.ServiceExePath;

                    if (!string.IsNullOrEmpty(sevExePath))
                    {
                        //校驗exe文件是否存在
                        if (File.Exists(sevExePath))
                        {
                            ScanServiceManager(sevName, sevExePath);
                        }
                    }
                }
            }
            else
            {
                WriteLog("沒有配置需要監控的服務!");
            }
        }

        /// <summary>
        /// 查找服務的進程
        /// 有則判斷進程是否運行,非運行狀態則啟動
        /// </summary>
        public static void ScanServiceManager(string serviceName, string serviceExePath)
        {
            try
            {
                ServiceController sevCtrler = new ServiceController(serviceName);
                //該服務已存在
                //如果服務狀態不為啟動
                if (sevCtrler.Status != ServiceControllerStatus.Running)
                {
                    sevCtrler.Start();
                }
                //創建監控線程
                WatchService(serviceName);
            }
            catch (Exception ex)
            {
                //該服務不存在
                WriteLog(string.Format(ex.Message));
            }
        }

        /// <summary>
        /// 為配置的進程添加監控進程
        /// </summary>
        /// <param name="pro"></param>
        /// <param name="processAddress"></param>
        public static void WatchService(string ServiceName)
        {
            ServiceMonitor monitor = new ServiceMonitor(ServiceName);
            Thread thread = new Thread(new ThreadStart(monitor.Monitor));
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 寫日志 
        /// </summary>
        /// <param name="errMessage"></param>
        public static void WriteLog(string errMessage)
        {
            string logPath = _logPath;
            //沒有配置日志目錄,不記錄
            if (!string.IsNullOrEmpty(logPath))
            {
                lock (_logLocker)
                {
                    string fullName = string.Format("{0}\\{1}.log", logPath, DateTime.Now.ToString("yyyy-MM-dd"));
                    if (!File.Exists(fullName))
                    {
                        File.Create(fullName).Close();
                    }
                    using (StreamWriter sw = new StreamWriter(fullName, true, Encoding.UTF8))
                    {
                        sw.WriteLine(String.Format("[{0}]{1}", DateTime.Now.ToString("hh:mm:ss fff"), errMessage));
                        sw.Close();
                    }
                }
            }
        }

        public class ServiceProcessInfo
        {
            /// <summary>
            /// 服務名稱
            /// </summary>
            public string ServiceName
            {
                get;
                set;
            }
            /// <summary>
            /// 應用程序位置
            /// </summary>
            public string ServiceExePath
            {
                get;
                set;
            }
        }


    }

上面ScanServiceManager方法中,使用serviceName實例化ServiceController對象,並啟用一個單獨的線程對其輪詢,監控其狀態;否則只會對第一個服務進行監控后阻塞。

    public class ServiceMonitor
    {
        /// <summary>
        /// 服務名稱
        /// </summary>
        private string _ServiceName;

        public string ServiceName
        {
            get { return _ServiceName; }
            set { _ServiceName = value; }
        }

        public ServiceMonitor(string ServiceName)
        {
            this._ServiceName = ServiceName;
        }

        /// <summary>
        /// 監聽服務
        /// </summary>
        public void Monitor()
        {
            while (true)
            {
                try
                {
                    ServiceController ctrler = new ServiceController(_ServiceName);
                    if (ctrler.Status != ServiceControllerStatus.Running)
                    {
                        ServiceSearch.WriteLog(string.Format("正在啟動服務{0}...", _ServiceName));
                        ctrler.Start();
                        ServiceSearch.WriteLog(string.Format("服務{0}啟動成功!", _ServiceName));
                    }
                }
                catch (Exception ex)
                {
                    ServiceSearch.WriteLog(string.Format("服務{0}啟動失敗,錯誤原因:{1}", _ServiceName, ex.Message));
                }
                Thread.Sleep(1000 * 40);
            }
        }

    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM