本文首發(fā)于:碼友網(wǎng)--一個專注.NET/.NET Core開發(fā)的編程愛好者社區(qū)。
文章目錄
C#/.NET基于Topshelf創(chuàng)建Windows服務的系列文章目錄:
- C#/.NET基于Topshelf創(chuàng)建Windows服務程序及服務的安裝和卸載 (1)
- 在C#/.NET應用程序開發(fā)中創(chuàng)建一個基于Topshelf的應用程序守護進程(服務) (2)
- 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();
}
}
}
僅此而已庄拇。
編寫好后,生成或者運行一下這個項目。你會看到一個控制臺應用程序界面措近,如:
實現(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.cs
和ProcessorHelper.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ā)的你有所幫助。
源代碼下載
本示例代碼托管地址可以在原出處找到:示例代碼下載地址