在C#/.NET应用程序开发中创建一个基于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开发的你有所帮助。
源代码下载
本示例代码托管地址可以在原出处找到:示例代码下载地址
- 在 .NET 中开发基于 Chrome 内核的浏览器-创建一个简单浏览器 分类: C# 2014-10-27 16:27 593人阅读 评论(0) 收藏
- 基于.NET/C#开发跨平台Windows Phone 7、iPhone及Android应用程序
- 70-316 使用Microsoft Visual C# .NET and Microsoft Visual Studio .NET 开发及实现基于Windows的应用程序 考点整理
- .NET跨平台实践:用C#开发Linux守护进程
- C#/.NET基于Topshelf创建Windows服务程序及服务的安装和卸载(极速,简洁)
- .NET跨平台实践:用C#开发Linux守护进程-Daemon
- 使用Apworks开发基于CQRS架构的应用程序(六):创建.NET WCF服务
- .NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇
- [2]项目创建-使用C#.NET开发基于本地数据缓存的PC客户端
- 在 .NET 中开发基于 Chrome 内核的浏览器-创建一个简单浏览器 分类: C# 2014-10-27 16:27 594人阅读 评论(0) 收藏
- 开发基于ASP.NET WebService的图片验证码服务
- 如何用VB.Net创建一个三层的数据库应用程序
- 怎样通过Visual C#.net创建一个DTS任务
- 如何使用C#创建一个三层的数据库应用程序
- C#+ASP.NET开发基于Web的RSS阅读器
- Visual Studio 2008开发新特性系列课程(10):使用Visual Studio 2008和.NET Compact Framework 3.5创建Mobile应用程序
- 如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
- 一个简单的AJAX实现,基于C#的ASP.Net,包括服务器端的程序代码
- C#+ASP.NET开发基于Web的RSS阅读器
- 在服务中创建用户进程的方法(C#版)