在C#/.NET應用程序開發(fā)中創(chuàng)建一個基于Topshelf的應用程序守護進程(服務)

本文首發(fā)于:碼友網(wǎng)--一個專注.NET/.NET Core開發(fā)的編程愛好者社區(qū)。

文章目錄

C#/.NET基于Topshelf創(chuàng)建Windows服務的系列文章目錄:

  1. C#/.NET基于Topshelf創(chuàng)建Windows服務程序及服務的安裝和卸載 (1)
  2. 在C#/.NET應用程序開發(fā)中創(chuàng)建一個基于Topshelf的應用程序守護進程(服務) (2)
  3. C#/.NET基于Topshelf創(chuàng)建Windows服務的守護程序作為服務啟動的客戶端桌面程序不顯示UI界面的問題分析和解決方案 (3)

前言

在上一篇文章《C#/.NET基于Topshelf創(chuàng)建Windows服務程序及服務的安裝和卸載》中,我們了解發(fā)C#/.NET創(chuàng)建基于Topshelf Windows服務程序的大致流程胞皱,參數(shù)配置以及服務的安裝和卸載。同時阔拳,我們也使用一個簡單的定時任務演示了Topshelf服務的執(zhí)行情況库正。

今天我將繼續(xù)為大家分享關于Topshelf主題的技術文章。本文主要演示在C#/.NET應用程序開發(fā)中創(chuàng)建一個基于Topshelf的應用程序守護進程(服務)幢痘。

創(chuàng)建一個演示應用程序

首先,打開之前我們創(chuàng)建的[TopshelfDemoService.sln]解決方案掀泳。在這個解決方案中再創(chuàng)建一個名為TopshelfDemo.Client的客戶端控制臺應用程序雪隧,這個客戶端程序即是我們需要使用[TopshelfDemoService]守護的。只是為了演示员舵,所以客戶端并沒有實際意義的邏輯和功能脑沿,在Program.cs文件中,添加如下示例代碼:

using System;

namespace TopshelfDemo.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("這是一個由[碼友網(wǎng)]創(chuàng)建的ERP系統(tǒng)示例程序马僻,目前正在運行...");
            Console.WriteLine("技術支持:碼友網(wǎng)(https://codedefautl.com) by Rector");
            Console.ReadLine();
        }
    }
}

僅此而已庄拇。

編寫好后,生成或者運行一下這個項目。你會看到一個控制臺應用程序界面措近,如:

image

實現(xiàn)守護程序功能

再回到項目[TopshelfDemoService]中溶弟,打開類文件HealthMonitorService.cs,其中的定時功能演示的是一個檢查某系統(tǒng)健康狀況的任務瞭郑,現(xiàn)在我們把定時任務功能改為守護某個或者某些應用程序辜御。

這里為了演示方便,沒有重新創(chuàng)建服務類屈张,在實際項目中擒权,你也可以根據(jù)自己的情況創(chuàng)建不同的服務類。

修改其中代碼為如下所示:

using System;
using System.Collections.Generic;
using System.Timers;

namespace TopshelfDemoService
{
    internal class HealthMonitorService
    {
        /// <summary>
        /// 檢測周期計時器
        /// </summary>
        private readonly Timer _timer;
        /// <summary>
        /// 檢測周期(秒)
        /// </summary>
        private int _monitorInterval = 10;
        /// <summary>
        /// 要守護的應用程序列表
        /// </summary>
        private List<DaemonApplicationInfo> _daemonApps { get; set; }

        public HealthMonitorService()
        {
            // 初始化要守護的應用程序列表
            // 實際項目中阁谆,你可以將這里的初始化參數(shù)放到配置文件/數(shù)據(jù)庫/緩存中(怎么方便怎么來)
            _daemonApps = new List<DaemonApplicationInfo> {
                new DaemonApplicationInfo {
                    ProcessName ="TopshelfDemo.Client",  // 請根據(jù)你的情況填寫
                    AppDisplayName ="TopshelfDemo Client", // 請根據(jù)你的情況填寫
                    AppFilePath =@"D:\Projects\github\TopshelfDemoService\TopshelfDemo.Client\bin\Debug\TopshelfDemo.Client.exe" // 這里的路徑請根據(jù)你的實際情況填寫
                }
            };
            _timer = new Timer(_monitorInterval*1000) { AutoReset = true };
            _timer.Elapsed += (sender, eventArgs) => Monitor();
        }

        /// <summary>
        /// 守護應用程序的方法
        /// </summary>
        private void Monitor()
        {
            foreach (var app in _daemonApps)
            {
                // 判斷當前進程是存已啟動
                if (ProcessorHelper.IsProcessExists(app.ProcessName))
                {
                    Console.WriteLine("Application[{0}] already exists.", app.ProcessName);
                    return;
                }
                try
                {
                    // 當前主機進程列表中沒有需要守護的進程名稱碳抄,則啟動這個進程對應的應用程序
                    ProcessorHelper.RunProcess(app.AppFilePath, app.Args);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Start application failed:{0}", ex);
                }
            }            
        }

        public void Start()
        {
            _timer.Start();
        }
        public void Stop()
        {
            _timer.Stop();
        }
    }
}

新建類DaemonApplicationInfo.csProcessorHelper.cs,編寫如下代碼场绿。

DaemonApplicationInfo.cs(需守護的應用程序?qū)嶓w類):

namespace TopshelfDemoService
{
    /// <summary>
    /// 需守護的應用程序?qū)嶓w
    /// </summary>
    public class DaemonApplicationInfo
    {
        /// <summary>
        /// 進程中顯示的名稱
        /// </summary>
        public string ProcessName { get; set; }
        /// <summary>
        /// 應用程序安裝路徑
        /// </summary>
        public string AppFilePath { get; set; }
        /// <summary>
        /// 應用程序的名稱
        /// </summary>
        public string AppDisplayName { get; set; }

        /// <summary>
        /// 參數(shù)
        /// </summary>
        public string Args { get; set; }
    }
}

ProcessorHelper.cs(進程處理幫助類):

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace TopshelfDemoService
{
    /// <summary>
    /// 進程處理幫助類
    /// </summary>
    internal class ProcessorHelper
    {
        /// <summary>
        /// 獲取當前計算機所有的進程列表(集合)
        /// </summary>
        /// <returns></returns>
        public static List<Process> GetProcessList()
        {
            return GetProcesses().ToList();
        }

        /// <summary>
        /// 獲取當前計算機所有的進程列表(數(shù)組)
        /// </summary>
        /// <returns></returns>
        public static Process[] GetProcesses()
        {
            var processList = Process.GetProcesses();
            return processList;
        }

        /// <summary>
        /// 判斷指定的進程是否存在
        /// </summary>
        /// <param name="processName"></param>
        /// <returns></returns>
        public static bool IsProcessExists(string processName)
        {
            return Process.GetProcessesByName(processName).Length > 0;
        }

        /// <summary>
        /// 啟動一個指定路徑的應用程序
        /// </summary>
        /// <param name="applicationPath"></param>
        /// <param name="args"></param>
        public static void RunProcess(string applicationPath, string args = "")
        {
            try
            {
                var psi = new ProcessStartInfo
                {
                    FileName = applicationPath,
                    WindowStyle = ProcessWindowStyle.Normal,
                    Arguments = args
                };
                Process.Start(psi);
            }
            catch{}
        }
    }
}

完成以上編碼后剖效,我們將項目程序[TopshelfDemo.Client]和[TopshelfDemoService]先都關閉掉(如果已運行),接著運行項目[TopshelfDemoService]焰盗,下面就是見證奇跡的時刻啦:

[圖片上傳失敗...(image-bd794-1555480622536)]

可以看到璧尸,守護程序[TopshelfDemoService]自動啟動了客戶端程序[TopshelfDemo.Client.exe],并且只會啟動一個客戶端實例程序姨谷。當我們把客戶端關閉后逗宁,下次守護程序檢測的時候客戶端程序又會被重啟。

遺留問題

如果你正高高興興地將TopshelfDemoService作為Windows服務安裝梦湘,那么你可能會遇到這個問題瞎颗,即守護進程正常運行,客戶端程序也能正常地被守護并且啟動捌议,在Windows的"任務管理器"中也可以找到客戶端的進程哼拔,但卻看不到客戶端程序的UI界面。

這是怎么回事呢瓣颅?倦逐??是不是哪里出錯了呢宫补?檬姥??應該如何解決呢粉怕?健民??

預知后事如何請聽下回分解(未完待續(xù))...

好了贫贝,今天的在C#/.NET應用程序開發(fā)中創(chuàng)建一個基于Topshelf的應用程序守護進程(服務)的分享就到這里秉犹。

我是Rector蛉谜,希望本文對C#/.NET開發(fā)的你有所幫助。

源代碼下載

本示例代碼托管地址可以在原出處找到:示例代碼下載地址

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末崇堵,一起剝皮案震驚了整個濱河市型诚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鸳劳,老刑警劉巖狰贯,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異棍辕,居然都是意外死亡暮现,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門楚昭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拍顷,你說我怎么就攤上這事抚太。” “怎么了昔案?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵尿贫,是天一觀的道長。 經(jīng)常有香客問我踏揣,道長庆亡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任捞稿,我火速辦了婚禮又谋,結果婚禮上,老公的妹妹穿的比我還像新娘娱局。我一直安慰自己彰亥,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布衰齐。 她就那樣靜靜地躺著任斋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耻涛。 梳的紋絲不亂的頭發(fā)上废酷,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音抹缕,去河邊找鬼澈蟆。 笑死,一個胖子當著我的面吹牛歉嗓,可吹牛的內(nèi)容都是我干的丰介。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哮幢!你這毒婦竟也來了带膀?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤橙垢,失蹤者是張志新(化名)和其女友劉穎垛叨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柜某,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡嗽元,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了喂击。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剂癌。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翰绊,靈堂內(nèi)的尸體忽然破棺而出佩谷,到底是詐尸還是另有隱情,我是刑警寧澤监嗜,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布谐檀,位于F島的核電站,受9級特大地震影響裁奇,放射性物質(zhì)發(fā)生泄漏桐猬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一刽肠、第九天 我趴在偏房一處隱蔽的房頂上張望溃肪。 院中可真熱鬧,春花似錦五垮、人聲如沸乍惊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽润绎。三九已至,卻和暖如春诞挨,著一層夾襖步出監(jiān)牢的瞬間莉撇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工惶傻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棍郎,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓银室,卻偏偏與公主長得像涂佃,于是被迫代替她去往敵國和親励翼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容