在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)

59次阅读

共计 4371 个字符,预计需要花费 11 分钟才能阅读完成。

本文首发于:码友网 – 一个专注.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 开发的你有所帮助。
源代码下载
本示例代码托管地址可以在原出处找到:示例代码下载地址

正文完
 0