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

时间:2022-09-20 14:02:57

本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区。

文章目录

C#/.NET基于Topshelf创建Windows服务的系列文章目录:

  1. C#/.NET基于Topshelf创建Windows服务程序及服务的安装和卸载 (1)
  2. 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务) (2)
  3. 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();
}
}
}

仅此而已。

编写好后,生成或者运行一下这个项目。你会看到一个控制台应用程序界面,如:

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

实现守护程序功能

再回到项目[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.csProcessorHelper.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],下面就是见证奇迹的时刻啦:

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

可以看到,守护程序[TopshelfDemoService]自动启动了客户端程序[TopshelfDemo.Client.exe],并且只会启动一个客户端实例程序。当我们把客户端关闭后,下次守护程序检测的时候客户端程序又会被重启。

遗留问题

如果你正高高兴兴地将TopshelfDemoService作为Windows服务安装,那么你可能会遇到这个问题,即守护进程正常运行,客户端程序也能正常地被守护并且启动,在Windows的"任务管理器"中也可以找到客户端的进程,但却看不到客户端程序的UI界面。

这是怎么回事呢???是不是哪里出错了呢???应该如何解决呢???

预知后事如何请听下回分解(未完待续)...

好了,今天的在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)的分享就到这里。

我是Rector,希望本文对C#/.NET开发的你有所帮助。

源代码下载

本示例代码托管地址可以在原出处找到:示例代码下载地址

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

  1. Win32 程序开发:创建一个应用程序窗口

    一.创建一个应用程序窗口 代码如下: // 头文件 #include <windows.h> // 全局变量 WCHAR g_lpszClassName[] = L"CLASSN ...

  2. 如何在HoloLens中创建一个2D的Hello World程序

    注:本文提及到的代码示例下载地址 > How to build an "Hello World" 2D app in HololLens. HoloLens 是微软的一款MR ...

  3. Dynamics CRM - 在 Dynamics CRM 开发中创建一个 Entity 对象

    在 Dynamics CRM 的开发中,我们时不时需要创建 Entity 对象,而对于如何创建 Entity 对象,在 C# plugin 和 JS 的写法存在些许差异. 一.C# Plugin 创建 ...

  4. Win32 程序开发入门:一个最简单的Win32程序

    一.什么是 Win32 Win32 是指 Microsoft Windows 操作系统的 32 位环境,与 Win64 都为 Windows 常见环境. 这里再介绍下 Win32 Applicatio ...

  5. IOS程序开发中-跳转到 发送短信界面 实现发短信

    前言:我发现我标题取的不好,谁帮我取个承接上下文的标题?评论一下,我改 项目需求:在程序开发中,我们需要在某个程序里面发送一些短信验证(不是接收短信验证,关于短信验证,传送门:http://www.c ...

  6. AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  7. 程序开发中的术语,如IDE&comma;OOP等等

    我们在开发程序过程中,会用到一些与编译有关的术语,比如:[编辑器.编译器.调试器.连接器,链接器.解释器,集成开发环境(Integrated Development Environment,IDE). ...

  8. 在IntelliJ IDEA中创建和运行java&sol;scala&sol;spark程序

    本文将分两部分来介绍如何在IntelliJ IDEA中运行Java/Scala/Spark程序: 基本概念介绍 在IntelliJ IDEA中创建和运行java/scala/spark程序 基本概念介 ...

  9. 使用 Android Studio 开发工具创建一个 Android 应用程序,显示一行文字&OpenCurlyDoubleQuote;Hello Android”,并将应用程序的名称更改为&OpenCurlyDoubleQuote;FirstApp”。

    需求说明: 使用 Android Studio 开发工具创建一个 Android 应用程序,显示一行文字"Hello Android",并将应用程序的名称更改为"Firs ...

随机推荐

  1. linux 用户管理&lpar;一&rpar;

    本节内容梗概: 1.用户管理配置文件 2.用户管理命令 3.用户组管理命令 4.批量添加用户 5.用户授权 学东西先讲原理,所以从配置文件入手 1.用户信息文件  /etc/passwd 存放了用户的 ...

  2. Winform自定义窗体样式,实现标题栏可灵活自定义

    最近在编写C/S结构应用程序时,感觉窗体的标题栏样式太死板了,标题文字不能更改大小.颜色.字体等,按钮不能隐藏等问题,在网上也查找了许多相关的资料,没有找到合适的解决方案,发现许多人也在寻求这个问题, ...

  3. svn 备份后双机同步热备失效,提示 W200007 target server does not support atomic revision property edits svynsync&colon;E170009

    svn 备份后双机同步热备失效,提示 W200007 target server does not support atomic revision property edits; consider u ...

  4. jQuery事件绑定方式(转)

    bind() 简要描述 bind()向匹配元素添加一个或多个事件处理器. 使用方式 $(selector).bind(event,data,function) event:必需项:添加到元素的一个或多 ...

  5. SQL Server2008数据库自动备份步骤

    一,  在电脑开始菜单中选择“SQL Server Management Studio”双击.在出现的界面中点击“连接”按钮. 二,  在出现的“ Microsoft SQL Server Manag ...

  6. 合理计划 dictionary cache 大小

    [数据字典缓冲区(Data Dictionary Cache)  ] 用于存放Oracle系统管理自身所需要的所有信息,包括登录的用户名.用户对象.权限等. 查看 data dictionary ca ...

  7. &lpar;转&rpar; xcodebuild和xcrun自动化编译ipa包 笔记

    转自:http://blog.csdn.net/totogo2010/article/details/8883100 打包过程 xcodebuild负责将工程源文件编译成xxx.app xcrun负责 ...

  8. Windows下的DOM操作

    前言:这学期学Linux之后,发现用命令行的方式来操作电脑还是很好玩的~写这篇随笔来总结下Windows环境下通过DOS来执行命令的操作,希望能帮到您~自己忘记的时候能回来复习emmm 启动DOS环境 ...

  9. 这是一个新的开始at this very monment

    简单的介绍下此时自己的情况,和对近几年所做的事做一个总结,并展望下自己的未来和对自己的期待.我会将我的博客分成两种,一个是我的学习笔记,另一个是我的生活记录. 2018年六月底我毕业于一个普通的二本, ...

  10. hihocoder 后缀自动机四&&num;183&semi;重复旋律6

    题目 对于\(k\in[1,n]\)求出长度为\(k\)的子串出现次数最多的出现了多少次 我直到现在才理解后缀自动机上的子树和是什么意思 非常显然的一点是 \[endpos(link(u))⊇endp ...