天天看點

c# 守護程序,WPF程式自守護

原文: c# 守護程序,WPF程式自守護

版權聲明:本文為部落客原創文章,轉載請注明出處。 https://blog.csdn.net/lwwl12/article/details/79035246

如何防止wpf程式異常關閉,守護程序是暫時能想到的最好方式。最好是能夠一次編碼就把守護程序的事情做完。

思路:程式打開時,首先打開守護程序;由守護程序打開主程式;守護程序與主程式間互相守護,任何一個挂了都能自動重新開機。

實作:Mutex互斥量,守護程序和主程式分别使用不同的互斥量,既可以防止重複打開軟體,又可以檢測程式是否在運作。

話不多說,直接上代碼:

/// <summary>
    /// App.xaml 的互動邏輯
    /// </summary>
    public partial class App : Application
    {
        /// <summary>
        /// 主程序互斥量
        /// </summary>
        private static System.Threading.Mutex mutex_main;

        /// <summary>
        /// 守護程序互斥量
        /// </summary>
        private static System.Threading.Mutex mutex_deamon;

        /// <summary>
        /// 是否為主程序
        /// </summary>
        private static bool isMain = false;

        /// <summary>
        /// 打開監視定時器
        /// </summary>
        public void RunMonitorTimer()
        {
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Elapsed += timer_Elapsed;
            timer.Interval = 2000;
            timer.Start();
        }

        /// <summary>
        /// 打開程式
        /// </summary>
        /// <param name="arg">參數不為null時打開主程序,否則打開守護程序</param>
        public void RunProcess(string arg = null)
        {
            /* 運作程式,不帶參數,打開守護程序 */
            Process m_Process = new Process();
            m_Process.StartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
            m_Process.StartInfo.Arguments = arg;
            m_Process.Start();
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            //根據參數判斷開啟主程序還是守護程序,守護程序不帶參數,主程序帶參數
            if (e.Args.Length < 1)
            {
                Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;

                //守護程序互斥量
                mutex_deamon = new System.Threading.Mutex(true, "MUTEX_DEAMON");
                if (mutex_deamon.WaitOne(0, false))
                {
                    RunMonitorTimer();

                    // 顯示一個自定義窗體,非主窗體,用于阻塞程序,窗體關閉後,守護程序将關閉
                    WndDeamon wnd = new WndDeamon();
                    wnd.ShowDialog();

                    this.Shutdown();
                }
                else
                {
                    MessageBox.Show("程式已經在運作!", "提示");
                    this.Shutdown();
                }
            }
            else
            {
                isMain = true;
                mutex_main = new System.Threading.Mutex(true, "MUTEX_MAIN");
                if (mutex_main.WaitOne(0, false))
                {
                    RunMonitorTimer();

                    base.OnStartup(e);
                    Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
                }
                else
                {
                    Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
                    MessageBox.Show("程式已經在運作!", "提示");
                    this.Shutdown();
                }
            }
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!isMain)
            {
                if (mutex_main == null)
                {
                    mutex_main = new System.Threading.Mutex(true, "MUTEX_MAIN");
                }
                if (mutex_main.WaitOne(0, false))
                {
                    //必須釋放mutex,否則将導緻mutex被占用,主程式不能允許
                    mutex_main.Dispose();
                    mutex_main = null;

                    RunProcess("main");
                }
            }
            else
            {
                if (mutex_deamon == null)
                {
                    mutex_deamon = new System.Threading.Mutex(true, "MUTEX_DEAMON");
                }
                if (mutex_deamon.WaitOne(0, false))
                {
                    mutex_deamon.Dispose();
                    mutex_deamon = null;

                    RunProcess();
                }
            }
        }
    }           

app.xaml中添加上述代碼即可,隻需定義WndDeamon.xaml窗體用于展示守護程序狀态,也可使用其他方式,有更好方式歡迎留言。