开发语言:C#
开发环境: Visual Studio 2022
微软官方文档:learn.microsoft.com/zh-cn/dotne…
最近在公司要求使用Windows服务作为消息队列的消费者,所以自行研究了一下C#中Windows服务如何创建以及如何使用,以及部署的方式。我是西瓜程序猿,此篇记录一下供大家参考学习。
一、Windows服务概述
1.1-Windows服务是什么?
Windows服务是在Windows操作系统上,以后台形式运行的应用程序。它们可以在系统启动时自动启动,并且独立于用户登录。Windows服务通常用于执行那些长时间运行、无需用户交互或需要在后台持续执行的任务。
1.2-Windows能用来做什么?
1.3-Windows服务有什么优势?
二、创建Windows服务
2.1-创建Windows服务项目
(1)打开【Visual Studio】开发工具,然后选择【 Windows 服务(.NET Framework) 】,点击下一步。注意:Windows服务只有在.NET Framework版本中才有了,在跨平台中使用Worker Service。(2)修改项目名称和项目存储目录,项目名称我写的是【MyDemoService】,然后框架我选择的是【.NET Farmework 4.8】,这个可以根据自己的需要填写和选择,然后点击【创建】。创建好的目录如下:【Program.cs】是主程序的入口,【Service1.cs】是服务的入口,可以创建多个,然后在Prodrams.cs中配置就好了。(3)【Service1】服务名称可以重命名修改,此处我重命名为【MyDemoService】, Program.cs文件中也相对应的也要进行修改。 (4)然后我们就可以在【MyDemoService】中写业务逻辑代码了,有很多种方式可以定位到要写的具体文件,先列举两种常用的。方法一:在【program.cs】文件中,找到这个类,按键盘上的F12可以直接进入查看文件。方法二:直接右击,然后点击【查看代码】。业务代码写到这里面:到这一步服务就创建好了,然后就写具体的业务代码就行了。注意:服务必须至少重写 OnStart 和 OnStop 才有用。
2.2-服务可以重写的方法
///
/// 服务启动:指示服务开始运行时应采取的操作。 必须在此过程中为服务编写代码才能执行有用的操作。
///
///
protected override void OnStart(string[] args)
{
}
///
/// 服务停止:指示在服务停止运行时应发生什么情况。
///
protected override void OnStop()
{
}
///
/// 暂停:指示在服务暂停时应发生什么情况。
///
protected override void OnPause()
{
}
///
/// 继续:指示服务在暂停后恢复正常运行时应发生什么情况。
///
protected override void OnContinue()
{
}
///
/// 停止前:指示在系统关闭之前应发生什么情况(如果此时服务正在运行)。
///
protected override void OnShutdown()
{
}
2.3-配置日志(log4net)
为了方便测试,先介绍一下如何使用log4net做日志记录,当日志启动时和停止时我们记录一下。
(1)我们在项目目录下新建一个文件夹【LogConfig】,然后再创建一个文件为【log4net.config】。(2)【log4net.config】内容如下。
(3)并且右击【【log4net.config】】文件,点击【属性】,然后将[复制到输出目录]设置为【始终复制】。(4)然后安装log4net。在项目目录中右击【引用】,然后点击【管理NuGet程序包】(5)然后点击浏览,搜索【log4net】,右侧点击安装。(6)重要:然后配置【AssemblyInfo.cs 】文件,如果不配置,是输出不了日志的。添加到底部即可:(如果你的【log4net.config】文件路径和我的不一样,记得修改成跟自己配置路径一样的)。代码:
[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "config", ConfigFile = "LogConfig/log4net.config", Watch = true)]
(7)然后就可以使用log4net了,首先在Windows服务中获得log4net的实例。代码:
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
三、Windows服务的运行和部署
3.1-服务基本配置
(1)点击我们的服务【MyDemoService.cs】,然后右击点击【添加安装程序】。(2)然后可以看到下面多出来了一个文件,就是安装程序。(3)然后可以修改基本信息,服务组件中的【服务名称】【服务描述】等等。我们右击【serviceInstall1】点击属性,然后进行修改。(4)然后点击【serviceProcessInstall1】右击属性,进行修改。
3.2-服务运行与发布
当我们直接按F5或者其他方式直接运行项目时,会提示:"无法从命令行或调试程序启动服务。必须首先安装 Windows服务(使用installutil.exe),然后用ServerExplorer、Windows服务管理工具或 NET START命令启动它。"。不是这样运行的,跟着下面步骤来操作运行与发布Windows服务吧。
前提注意:如果你设置的目标平台是x64,打开的目录会不一样,不然导致服务运行不起来。可以右击项目名,点击【属性】——>【生成】——>【目标平台】查看。如果不是x64版本,复制这个地址:
C:WindowsMicrosoft.NETFrameworkv4.0.30319
如果是x64版本,复制这个地址:
C:WindowsMicrosoft.NETFramework64v4.0.30319
**不然会报类似这种错误:**在初始化安装时发生异常: System.BadImageFormatException: 未能加载文件或程序集...
(1)然后我们把上面的地址(根据自己的环境选择)添加到环境变量中。点击【控制面板】——>【系统和安全】(2)然后点击【系统】(3)点击【高级系统设置】(4)点击【环境变量】(5)在【系统变量】中找到Path,然后点击【编辑】。(6)然后点击【新建】,然后把我们拷贝的目录复制到这里。然后点击确认即可。(7)测试是否配置成功,输入这个命令查看一下【InstallUtil】,如果是下面这样的内容说明成功了。(8)然后编辑解决方案和项目。(9)以管理员身份运行cmd命令,然后安装服务。
InstallUtil 项目启动执行文件全路径
西瓜程序猿的例子:
InstallUtil D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe
(10)出现这个说明安装成功了。(11)打开服务管理器,找到要启动的服务,然后右击启动服务。启动后可以看到日志也有了:(12)如果要卸载服务,可以运行这个命令:
InstallUtil /u 项目启动执行文件全路径
西瓜程序猿的例子:
InstallUtil /u D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe
3.3-常见命令
1、安装服务:InstallUtil 项目启动执行文件全路径
3、启动服务:net start 服务名
4、停止服务:net stop 服务名
4、卸载服务:InstallUtil /u 项目启动执行文件全路径
3.4-查看计算机事件
如果在启动Windows服务时报错,我们可以通过查看计算机事件查询到具体的报错信息。
(1)按键盘上的【Win+R】,然后输入【eventvwr.msc】(2) 然后点击确定,就可以打开事件查看器的窗口。在窗口左侧找到【Windows日志】——>【系统】,就可以看到电脑的开机关机及日志记录了。
3.5-在服务器上安装相同Windows服务的多个实例
这个方案比较全可以参考:www.u72.net/b/show-3173…
我是西瓜程序猿,用的是这种方法:(1)通过此命令可以部署多个,[servicename]唯一就行了,自己配置。
sc create [servicename] binpath= [path to your exe]
注意: [servicename]填写的是服务名称,[path to your exe] 是执行文件的路径,必须是完整路径,不要忘记binpath= 后面的空格。这种方法确实允许多次安装服务。但是服务安装程序提供的所有信息。 F.e.描述、登录类型等被忽略。
3.6-常见的错误
1、无法打开计算机“.”上的服务控制管理器
在“安装”阶段发生异常。
System.InvalidOperationException: 无法打开计算机“.”上的服务控制管理器。此操作可能需要其他特权。
引发了内部异常 System.ComponentModel.Win32Exception,错误消息如下: 拒绝访问。。
正在开始安装的“回退”阶段。
查看日志文件的内容以获得 D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe 程序集的进度。
该文件位于 D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.InstallLog。
正在回滚程序集“D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe”。
受影响的参数是:
logtoconsole =
logfile = D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.InstallLog
assemblypath = D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe
正在将事件日志还原到源 TestDemoServices 的前一状态。
“回退”阶段已成功完成。
已完成事务处理安装。
安装失败,已执行回退。
解决:权限不够,打开cmd时记得【以管理员身份】打开。
2、未能加载文件或程序集xxx的基个依赖项
在初始化安装时发生异常: System.BadImageFormatException: 未能加载文件或程序集“file://E:DebuginServers.sB惑的基个依赖项。试图加载格式不正确的程序。
解决:请看本文第【3.2】点
3、在执行【.bat】文件时,报路径不存在相关的错
** 执行命令**:InstallUtil /u D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe
错误信息:C:Windowssystem32>InstallUtil /u D:椤圭洰婕旂ず涓存椂淇濆瓨MyDemoServiceMyDemoServicebinDebugMyDemoService.exe Microsoft (R) .NET Framework 安装实用工具版本 4.8.9037.0 版权所有 (C) Microsoft Corporation。保留所有权利。 在初始化安装时发生异常: System.IO.FileNotFoundException: 未能加载文件或程序集“file:///D:椤圭洰婕旂ず涓存椂淇濆瓨MyDemoServiceMyDemoServicebinDebugMyDemoService.exe”或它的某一个依赖项。系统找不到指定的文件。。
分析:这个错是乱码导致的,执行的命令是这个【InstallUtil /u D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe】,但是在控制台里面显示的是这个【file:///D:椤圭洰婕旂ず涓存椂淇濆瓨MyDemoServiceMyDemoServicebinDebugMyDemoService.exe】。 出现了乱码,这可能是由于控制台编码设置不正确导致的 。解决:使用正确的编码,尝试将控制台编码设置为与文件路径所使用的编码一致。例如,如果文件路径是UTF-8编码,您可以在控制台中执行以下命令进行设置:
chcp 65001
截图:
四、高效工具:编写bat启动卸载服务
4.1-安装服务
我们可以创建一个文件【安装服务.bat】输入以下内容:
chcp 65001
REM Install
InstallUtil 项目启动执行文件全路径
pause
注意:执行这个命令需要【以管理员身份】运行,不然会报这个错误:
System.InvalidOperationException: 无法打开计算机“.”上的服务控制管理器。此操作可能需要其他特权。
引发了内部异常 System.ComponentModel.Win32Exception,错误消息如下: 拒绝访问。。
正确执行方式:
4.2-启动服务
我们可以创建一个文件【卸载服务.bat】输入以下内容:
REM Install
net start 服务名
pause
注意:执行这个命令需要【以管理员身份】运行,不然会报这个错误:
发生系统错误。
拒绝访问。
4.3-停止服务
我们可以创建一个文件【卸载服务.bat】输入以下内容:
REM Install
net stop 服务名
pause
注意:执行这个命令需要【以管理员身份】运行,不然会报这个错误:
发生系统错误。
拒绝访问。
4.4-卸载服务
我们可以创建一个文件【卸载服务.bat】输入以下内容:
chcp 65001
REM Install
InstallUtil /u 项目启动执行文件全路径
pause
版权声明:本文为原创文章,版权归 [西瓜程序猿] 所有,转载请注明出处,有任何疑问请私信咨询。
原文链接:juejin.cn/spost/72681…