目录

介绍

特征

准备此应用程序的步骤如下

1.创建Windows服务项目

2.将项目输出类型从Windows应用程序更改为控制台应用程序

3.安装log4net包

4.配置log4net

5.添加SampleBackgroundService类,其中包含我们的Windows服务将执行的实际后台操作

6.在自动生成的Windows服务类中更新代码

7.更新Program.cs文件中的Main 方法,使其在调试和释放模式下表现不同

8.使用InstallUtil.exe添加Service Installer组件以便能够安装此服务

9.在调试模式下运行应用程序以查看日志输出和调试

关于Windows服务的重要说明


  • 源代码(GitHub存储库)

介绍

Windows服务是非常强大的应用程序,可用于在后台执行许多不同类型的任务。他们可以在不需要任何用户登录的情况下启动,并且可以使用除登录用户之外的其他用户帐户运行。但是,如果通过遵循常规服务开发步骤开发Windows服务应用程序,即使在开发环境中也难以调试。

本文提出了一种不使用任何服务开发库(如Topshelf)开发Windows服务的不同方法,以便在开发阶段轻松监视和调试。

特征

示例项目具有以下特征:

  • 它在调试模式下作为控制台应用程序运行,在发布模式下作为常规Windows服务运行。
  • 根据日志类型,使用不同的文本颜色在控制台上显示日志消息。
  • Windows服务相关操作和实际后台任务处理操作是分开的,因此可以轻松地对实际服务操作进行单元测试。
  • 可以使用InstallUtil.exe安装和卸载服务。但是您不需要安装它来进行测试和调试。

准备此应用程序的步骤如下

该示例项目是使用Visual Studio 2017准备的。

1.创建Windows服务项目

在Visual Studio中,单击“File\New\Project。选择“Visual C#\Windows Desktop\Windows Service”项目类型。

2.将项目输出类型从Windows应用程序更改为控制台应用程序

右键单击项目名称并选择“属性 ”,打开项目属性。

从“输出类型 ”选择列表中选择控制台应用程序。

3.安装log4net包

从Package Manager控制台或Manage Nuget Packages菜单选项安装log4net nuget软件包。

4.配置log4net

log4net是一个非常强大的日志库,可以将日志写入许多目标,如文本文件,控制台,数据库,Windows事件日志,甚至可以将它们作为电子邮件发送。这些日志编写器(或目标)称为“appender”。log4net配置必须至少有一个appender,但它可能有很多。每个appender都有自己的设置。

log4net配置可以添加到app.config文件中,也可以是单独的文件。我更喜欢单独的文件的方法,因此为log4net添加两个配置文件,用于调试和发布模式。名称无关紧要,您可以将它们命名为“log4net.debug.config”和“log4net.prod.config”。Debug配置文件有两个appender; RollingFileAppender和ColoredConsoleAppender。生产配置文件还有两个appender; RollingFileAppender和EventLog。但EventLog appender已注释掉,如果要编写Windows事件日志,可以取消注释。

最小日志级别在<root>元素下定义为<level>配置元素。对于调试配置级别DEBUG,对于生产级别是INFO。有效级别是; DEBUG,INFO,WARN,ERROR。有关更多信息,请参阅log4net文档。

下一个配置步骤是告诉log4net库在调试和发布模式下使用哪个文件。为此,请打开AssemblyInfo.cs文件并为log4net添加程序集级别属性。添加这些行以在调试和释放模式下在两个文件之间切换。

#if DEBUG
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.debug.config", Watch = true)]
#else
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.prod.config", Watch = true)]
#endif

5.添加SampleBackgroundService类,其中包含我们的Windows服务将执行的实际后台操作

它是一个非常简单的类,具有用于启动和停止后台任务处理线程的Start、Stop方法和一个连续写入日志的线程方法。

class SampleBackgroundService
{//Get a logger for this class from log4net LogManagerprivate static ILog logger = LogManager.GetLogger(typeof(SampleBackgroundService));//Starts the threadpublic void Start() { ... }//Stops the threadpublic void Stop() { ... }//Service thread that performs background tasks and writes logsprivate void serviceThread(){while (!stopRequested){//Write different types of logs...}}
}

6.在自动生成的Windows服务类中更新代码

我已将自动添加的Windows Services类重命名为SampleWindowsService。此类继承自ServiceBase,并且是在启动或停止Windows服务时在其类中调用OnStart和OnStop方法。该类仅创建SampleBackgroundService类的实例并调用其Start和Stop方法。

public partial class SampleWindowsService : ServiceBase
{SampleBackgroundService sampleBackgroundService;public SampleWindowsService(){InitializeComponent();}//Called when the Windows service is startedprotected override void OnStart(string[] args){sampleBackgroundService = new SampleBackgroundService();sampleBackgroundService.Start();}//Called when the Windows service is stoppedprotected override void OnStop(){sampleBackgroundService.Stop();}
}

7.更新Program.cs文件中的Main 方法,使其在调试和释放模式下表现不同

创建新的Windows服务项目时,自动生成的Main 方法包含用于创建和启动自动生成的Windows服务的代码。但是,Windows服务无法作为常规应用程序启动和托管。因此,当您尝试运行该应用程序时会出现一条错误消息。

要运行和测试我们的应用程序,我们不需要创建真正的Windows服务实例,因为除了创建和启动SampleBackgroundService类的实例之外,它不包含任何代码。Main方法中的更新代码以调试模式创建并启动SampleBackgroundService类的实例,并作为控制台应用程序运行。但是在发布模式下创建并运行真正的Windows服务。

static void Main()
{ILog logger = LogManager.GetLogger(typeof(Program));#if DEBUG //Run as a regular console application in Debug mode//Manually create an instance of SampleBackgroundService class and call its start methodlogger.Info("Starting services...");SampleBackgroundService _backgroundService = new SampleBackgroundService();_backgroundService.Start();logger.Info("Services started. Press enter to stop...");Console.ReadLine();logger.Info("Stopping service...");_backgroundService.Stop();logger.Info("Stopped.");#else //Create and run the real Windows service instance in Release modeServiceBase[] ServicesToRun;ServicesToRun = new ServiceBase[]{new SampleWindowsService()};ServiceBase.Run(ServicesToRun);
#endif
}

8.使用InstallUtil.exe添加Service Installer组件以便能够安装此服务

要添加安装程序组件,请在解决方案资源管理器上双击SampleWindowsService.cs。它将显示服务的设计视图。

右键单击设计区域,然后单击上下文菜单中的“添加安装程序 ”。

这会将ProjectInstaller.cs和设计器文件添加到项目中。删除自动生成的代码ProjectInstaller.InitializeComponent()方法和自动生成的变量(serviceProcessInstaller1,serviceInstaller1)。

将以下代码添加到ProjectInstaller.cs文件中:

public partial class ProjectInstaller : Installer
{public const string SERVICE_NAME = "Sample Background Service";private readonly ServiceProcessInstaller m_ServiceProcessInstaller;private readonly ServiceInstaller m_ServiceInstaller;public ProjectInstaller(){//Installer that installs the process (in this case 'DebuggableWindowsService.exe')//There can be only one ServiceProcessInstallerm_ServiceProcessInstaller = new ServiceProcessInstaller();m_ServiceProcessInstaller.Account = ServiceAccount.LocalSystem;//Installer that registers actual Windows Service implementations in the application//There may be one or more ServiceInstallerm_ServiceInstaller = new ServiceInstaller();m_ServiceInstaller.ServiceName = SERVICE_NAME;m_ServiceInstaller.Description = "";m_ServiceInstaller.StartType = ServiceStartMode.Automatic;m_ServiceInstaller.DelayedAutoStart = true;            Installers.Add(m_ServiceProcessInstaller);Installers.Add(m_ServiceInstaller);InitializeComponent();}//...}

如果要在安装服务之前和之后执行任何任务,你可以重写相应的基类方法,例如OnBeforeInstall,OnBeforeUninstall...

您无需安装(或向Windows服务注册表注册服务)您的服务即可运行和调试。但是,如果需要,可以使用InstallUtil.exe来安装和卸载服务。InstallUtil.exe位于.NET Framework安装文件夹下。例如,“C:\Windows\Microsoft.NET\Framework\v4.0.30319”。

要注册该服务,请打开命令行窗口并 使用可执行文件的完整路径运行InstallUtil.exe。您可能需要“以管理员身份”运行命令行窗口才能注册服务。

C:\Windows\Microsoft.NET\Framework\v4.0.30319>InstallUtil.exe
"D:\DebuggableWindowsService\src\bin\Release\DebuggableWindowsService.exe"

要卸载服务,请使用/u选项运行相同的命令。

C:\Windows\Microsoft.NET\Framework\v4.0.30319>InstallUtil.exe
/u "D:\DebuggableWindowsService\src\bin\Release\DebuggableWindowsService.exe"

9.在调试模式下运行应用程序以查看日志输出和调试

下面是应用程序在调试模式下运行时显示的示例输出。

关于Windows服务的重要说明

Windows服务应用程序在几个方面与其他常规应用程序不同。因此,应用程序在调试(控制台应用程序模式)和发布(Windows服务模式)模式下的行为可能不同。

首先,当您在调试模式下运行应用程序时,其工作目录将是可执行文件所在的路径,例如“D:\DebuggableWindowsService\src\bin\Release\DebuggableWindowsService.exe”。

但是,当您使用InstallUtil.exe或安装应用程序安装它并从Windows服务管理应用程序运行它时,其工作目录将是“C:\Windows\System32" or "C:\Windows\SysWOW64”,具体取决于您是否服务是64位或32位,以及它是在32位还是64位Windows上运行。

如果要在安装目录而不是系统目录中读取或写入文件,可以在启动时更改工作目录。例如:

Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

其次,Windows服务可能使用与登录用户不同的用户帐户运行。当应用程序作为真正的Windows服务运行时,某些在调试模式下运行的操作可能无法运行。这些操作的示例是访问目录或网络路径,打开端口...

第三,Windows服务没有用户界面,通常无法显示用户界面。Windows操作系统阻止了他们对显卡的访问。遗憾的是,无法使用Windows服务中的强大GPU。要了解有关此限制的更多信息,请搜索“Session 0 Isolation”。

要从Windows服务显示用户界面,请查看本文,Windows服务是否可以使用GUI?如果 Windows服务有一个GUI?。

使用C#调试Windows服务模板项目相关推荐

  1. Windows服务二:测试新建的服务、调试Windows服务

    一.测试Windows服务 为了使Windows服务程序能够正常运行,我们需要像创建一般应用程序那样为它创建一个程序的入口点.像其他应用程序一样,Windows服务也是在Program.cs的Main ...

  2. 调试windows服务

    调试服务 在调试配置中生成你的服务. 安装你的服务. 从 "服务控制管理器"."服务器资源管理器"或代码启动服务. 使用管理凭据启动 Visual Studio ...

  3. Windows服务的创建、安装、调试

    1:新建一个WINDOWS服务项目: 2:打开自动生成的Server1的源代码,可以在其中看到OnStart与OnStop方法,代表的是服务的启动与关闭: 3:将事件日志中的写日志的方法COPY到Se ...

  4. Windows服务的快速搭建与调试(C#图解)

    目录 一.什么是Windows 服务? 二.创建Windows 服务与安装/卸载批处理. 三.调试Windows 服务. 正文 一.什么是Windows 服务? 答:Microsoft Windows ...

  5. 如何使用VS+C#创建,优雅自动化的安装(不使用命令行),调试,更新Windows服务

    轻量级,即是服务部署器,又是服务本体,免命令行,免bat.直接部署和调试代码的东西,也就长这样了. 看这一篇文章应该可以把你构建和调试windows服务这些事儿玩儿转. 一.创建服务 1.可以打开VS ...

  6. .NET Core Generic Host项目使用Topshelf部署为Windows服务

    1..NET Core Generic Host是什么? 在.NET Core 2.1版本加入了一种新的Host,即Generic Host(通用主机). 现在在2.1版本的Asp.Net Core中 ...

  7. C#制作Windows service服务系列二:演示一个定期执行的windows服务及调试(windows service)(转载)...

    系列一: 制作一个可安装.可启动.可停止.可卸载的Windows service(downmoon原创) 系列二:演示一个定期执行的windows服务及调试(windows service)(down ...

  8. 用.NET创建Windows服务

    用.NET创建Windows服务 译者说明:我是通过翻译来学习C#的,文中涉及到的有Visual Studio.NET有关操作,我都根据中文版的VS.NET显示信息来处理的,可以让大家不致有误解. 作 ...

  9. 演练:在组件设计器中创建 Windows 服务应用程序

    http://msdn.microsoft.com/zh-cn/library/zt39148a(v=vs.80).aspx 演练:在组件设计器中创建 Windows 服务应用程序 .NET Fram ...

最新文章

  1. openwrt 安装尔雅云_[网络]openwrt的阿里云编译
  2. GitHub 的前世今生
  3. [基础题]2.(*)利用接口做参数,写个计算器,能完成加减乘除运算。
  4. Linux网络DNS配置反向解析与构建主从域名服务器
  5. threadlocal内存泄露_深入理解 ThreadLocal
  6. delphi 中assert
  7. Reflex WMS入门系列二十四:拆托(HD Breakdown)
  8. 美国国家机器人计划2.0部分项目简介
  9. 何文江先生出任创意信息集团总经理
  10. 被蠢人、穷人与聪明人放弃的“概率权”
  11. 有限Abel群的一维复表示
  12. 实战 SQL:销售数据的小计/合计/总计以及数据透视表
  13. linux下进程管理的原理,Linux进程管理:supervisor和nohup原理及使用
  14. Win10图片打开方式没有“Windows照片查看器”
  15. The Staircases
  16. c语言逐行扫描打印图案,用逐行扫描法读取4X4键盘矩阵,不能扫描出第一列按键?...
  17. 驾校网站模板 php_汽车驾照培训的网站模板
  18. c井语言和SQL第一章上机1,第一章 SQL Server 数据库基础复习内容(上机)
  19. 微信小程序常用组件分享
  20. 6. 多列布局column

热门文章

  1. matlab与水库调度,蛙跳算法优化水库调度,全局迭代中最优解未更新
  2. vant 动态 粘性布局_CSS Viewport 单位,很多人还不知道使用它来快速布局
  3. 全盘镜像只还原c盘有影响么_如何正确的清理C盘
  4. c语言随机产生10个30 100,c语言编写随机产生10个100~200之间整数,幷按从大到小排序...
  5. 百搭手绘卡通牛年吉祥生肖素材,萌到心里的小牛
  6. 美食合成海报,脑洞开得有点Hold不住!!
  7. 学计算机的想当警察去一线,想当警察但又怕收入不高,我到底该选择梦想还是现实?...
  8. python装饰器 property_介绍Python的@property装饰器的用法
  9. Linux内存管理:ELF文件格式
  10. CentOS开机流程