监听端口守护程序

场景:公司写的程序老是崩掉,查原因无果,各种改版无果,遂写一个守护程序来监听该程序,如果崩掉,就自动重启。


1. 添加进程管理类 ProcessHelper

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Guard
{
    public class ProcessHelper
    {
        /// <summary>
        /// 查看进程是否存在
        /// </summary>
        /// <param name="name">进程名称</param>
        /// <returns></returns>
        public static bool Exist(string name)
        {
            return Process.GetProcessesByName(name).Length > 0;
        }

        /// <summary>
        /// 开启进程
        /// </summary>
        /// <param name="path">进程所在物理路径</param>
        /// <returns></returns>
        public static void Start(string path)
        {
            Process m_Process = new Process();
            m_Process.StartInfo.FileName = path;
            //开启新的窗体
            m_Process.StartInfo.UseShellExecute = true;
            m_Process.Start();
         
        }

        /// <summary>
        /// 关闭进程
        /// </summary>
        /// <param name="name">进程名称</param>
        /// <returns></returns>
        public static void Stop(string name)
        {
            Process proc = Process.GetProcessesByName(name).FirstOrDefault();
            if (proc != null)
                proc.Kill();
        }
    }
}

 

2. 添加配置文件 App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
    <!--守护间隔时间-->
    <add key="second" value="10"/>
        <!--守护程序端口-->
        <add key="port" value="104"/>
        <!--守护程序路径-->
        <add key="path" value="D:\项目文件\_报告影像自助系统\trunk\DicomPrintDesktopV3\bin\Debug\LZIMC.ReportPrintSystem.DicomPrintDesktopV3.exe"/>
    </appSettings>
</configuration>

 

3. 在类型库里面添加引用 System.configuration,方便获取配置文件自定义的值

 

4. 实现代码

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;

namespace Guard
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int second = Convert.ToInt32(ConfigurationManager.AppSettings["second"]);
                int port = Convert.ToInt32(ConfigurationManager.AppSettings["port"]);
                string path = ConfigurationManager.AppSettings["path"];

                while (true)
                {
                    Console.WriteLine("Port: " + port + " status: " + (PortInUse(port) ? "存在" : "不存在"));
                    if (!PortInUse(port)) //如果监听的端口不存在,就启动对应的程序
                    {
                        WriteLog("启动端口" + port + "的程序");
                        ProcessHelper.Start(path);
                    }
                    Thread.Sleep(second * 1000);
                }
            }
            catch (Exception ex)
            {
                WriteLog("发生错误:" + ex.Message);
            }
        }

        /// <summary>
        /// 日志记录
        /// </summary>
        /// <param name="errMsg"></param>
        private static void WriteLog(string errMsg)
        {
            string sFilePath = AppDomain.CurrentDomain.BaseDirectory + "\\Log";
            string sFileName = DateTime.Now.ToString("yyyy-MM-dd") + ".log";
            sFileName = sFilePath + "\\" + sFileName;
            Directory.CreateDirectory(sFilePath);
            FileStream fs;
            StreamWriter sw;
            if (File.Exists(sFileName))
                fs = new FileStream(sFileName, FileMode.Append, FileAccess.Write);
            else
                fs = new FileStream(sFileName, FileMode.Create, FileAccess.Write);
            sw = new StreamWriter(fs);
            sw.WriteLine("时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            sw.WriteLine("信息:" + errMsg);
            sw.WriteLine("");
            sw.Close();
            fs.Close();
        }

        /// <summary>
        /// 判断端口是否占用
        /// </summary>
        /// <param name="port"></param>
        /// <returns></returns>
        public static bool PortInUse(int port)
        {
            bool inUse = false;

            IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
            IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();

            foreach (IPEndPoint endPoint in ipEndPoints)
            {
                if (endPoint.Port == port)
                {
                    inUse = true;
                    break;
                }
            }
            return inUse;
        }
    }
}

 

其他:程序崩掉,但没有自动关闭控制台的窗体,便不能通过端口监听到是否崩掉,遂修改系统注册表:

运行注册表编辑器,依次定位到 HKEY_CURRENT_USER\Software\Microsoft\Windows\WindowsError Reporting,
在右侧窗口中找到并双击打开DontshowUI,然后在弹出的窗口中将默认值“0”修改为“1”。 那么,当程序崩溃时,就不会再出现”xx程序已停止工作”的提示框,崩溃程序进程会自动退出。 这种修改系统注册表的方法是最方便和直接的,但会对所有程序生效。

如图:

监听端口守护程序

 

监听端口守护程序

上一篇:解决crontab定时任务只能按照固定时间开始执行,不能实现立即执行的问题


下一篇:B - The Tag Game( 树 的BFS)