在上一篇文章《C#/.NET基於Topshelf創建Windows服務程式及服務的安裝和卸載》中,我們瞭解發C#/.NET創建基於Topshelf Windows服務程式的大致流程,參數配置以及服務的安裝和卸載。同時,我們也使用一個簡單的定時任務演示了Topshelf服務的執行情況。 今天我將繼續... ...
本文首發於:碼友網--一個專註.NET/.NET Core開發的編程愛好者社區。
文章目錄
C#/.NET基於Topshelf創建Windows服務的系列文章目錄:
- C#/.NET基於Topshelf創建Windows服務程式及服務的安裝和卸載 (1)
- 在C#/.NET應用程式開發中創建一個基於Topshelf的應用程式守護進程(服務) (2)
- C#/.NET基於Topshelf創建Windows服務的守護程式作為服務啟動的客戶端桌面程式不顯示UI界面的問題分析和解決方案 (3)
前言
在上一篇文章《C#/.NET基於Topshelf創建Windows服務程式及服務的安裝和卸載》中,我們瞭解發C#/.NET創建基於Topshelf Windows服務程式的大致流程,參數配置以及服務的安裝和卸載。同時,我們也使用一個簡單的定時任務演示了Topshelf服務的執行情況。
今天我將繼續為大家分享關於Topshelf主題的技術文章。本文主要演示在C#/.NET應用程式開發中創建一個基於Topshelf的應用程式守護進程(服務)。
創建一個演示應用程式
首先,打開之前我們創建的[TopshelfDemoService.sln]解決方案。在這個解決方案中再創建一個名為TopshelfDemo.Client
的客戶端控制台應用程式,這個客戶端程式即是我們需要使用[TopshelfDemoService]守護的。只是為了演示,所以客戶端並沒有實際意義的邏輯和功能,在Program.cs
文件中,添加如下示例代碼:
using System;
namespace TopshelfDemo.Client
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("這是一個由[碼友網]創建的ERP系統示常式序,目前正在運行...");
Console.WriteLine("技術支持:碼友網(https://codedefautl.com) by Rector");
Console.ReadLine();
}
}
}
僅此而已。
編寫好後,生成或者運行一下這個項目。你會看到一個控制台應用程式界面,如:
實現守護程式功能
再回到項目[TopshelfDemoService]中,打開類文件HealthMonitorService.cs
,其中的定時功能演示的是一個檢查某系統健康狀況的任務,現在我們把定時任務功能改為守護某個或者某些應用程式。
這裡為了演示方便,沒有重新創建服務類,在實際項目中,你也可以根據自己的情況創建不同的服務類。
修改其中代碼為如下所示:
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()
{
// 初始化要守護的應用程式列表
// 實際項目中,你可以將這裡的初始化參數放到配置文件/資料庫/緩存中(怎麼方便怎麼來)
_daemonApps = new List<DaemonApplicationInfo> {
new DaemonApplicationInfo {
ProcessName ="TopshelfDemo.Client", // 請根據你的情況填寫
AppDisplayName ="TopshelfDemo Client", // 請根據你的情況填寫
AppFilePath =@"D:\Projects\github\TopshelfDemoService\TopshelfDemo.Client\bin\Debug\TopshelfDemo.Client.exe" // 這裡的路徑請根據你的實際情況填寫
}
};
_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(需守護的應用程式實體類):
namespace TopshelfDemoService
{
/// <summary>
/// 需守護的應用程式實體
/// </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>
/// 參數
/// </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>
/// 獲取當前電腦所有的進程列表(數組)
/// </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],下麵就是見證奇跡的時刻啦:
可以看到,守護程式[TopshelfDemoService]自動啟動了客戶端程式[TopshelfDemo.Client.exe],並且只會啟動一個客戶端實常式序。當我們把客戶端關閉後,下次守護程式檢測的時候客戶端程式又會被重啟。
遺留問題
如果你正高高興興地將TopshelfDemoService作為Windows服務安裝,那麼你可能會遇到這個問題,即守護進程正常運行,客戶端程式也能正常地被守護並且啟動,在Windows的"任務管理器"中也可以找到客戶端的進程,但卻看不到客戶端程式的UI界面。
這是怎麼回事呢???是不是哪裡出錯了呢???應該如何解決呢???
預知後事如何請聽下回分解(未完待續)...
好了,今天的在C#/.NET應用程式開發中創建一個基於Topshelf的應用程式守護進程(服務)的分享就到這裡。
我是Rector,希望本文對C#/.NET開發的你有所幫助。
源代碼下載
本示例代碼托管地址可以在原出處找到:示例代碼下載地址