使用C#创建安装Windows服务程序(干货)

2023年 8月 18日 17.5k 0

开发语言:C#
开发环境: Visual Studio 2022
微软官方文档:learn.microsoft.com/zh-cn/dotne…

最近在公司要求使用Windows服务作为消息队列的消费者,所以自行研究了一下C#中Windows服务如何创建以及如何使用,以及部署的方式。我是西瓜程序猿,此篇记录一下供大家参考学习。

一、Windows服务概述

1.1-Windows服务是什么?

Windows服务是在Windows操作系统上,以后台形式运行的应用程序。它们可以在系统启动时自动启动,并且独立于用户登录。Windows服务通常用于执行那些长时间运行、无需用户交互或需要在后台持续执行的任务。

1.2-Windows能用来做什么?

  • 后台任务和自动化:可以使用Windows服务来执行重复性的计划任务、数据同步、定期备份、报告生成等。
  • 网络服务:Windows服务可以作为网络服务器提供网络服务,如Web服务器、FTP服务器、邮件服务器等。
  • 定时任务:Windows服务可以创建定时任务并在指定时间间隔或特定事件发生时触发执行操作。
  • 数据处理:可以使用Windows服务进行数据处理、数据转换、数据清洗等批量处理任务。
  • 消息队列:可以用于消息队列的消费者,后台任务一直和消息队列保持长连接,需要消费时会自动接收到进行业务处理。
  • 1.3-Windows服务有什么优势?

  • 后台执行:Windows服务在后台运行,不会干扰用户的工作,也无需用户登录即可持续执行任务。
  • 系统级别权限:Windows服务可以在系统级别运行,具有更高的权限,可以访问系统资源和执行敏感操作。
  • 自动启动:Windows服务可以在系统启动时自动启动,确保任务始终处于运行状态。
  • 可靠性和稳定性:Windows服务被设计为长时间运行的应用程序,具有较高的可靠性和稳定性。
  • 二、创建Windows服务

    2.1-创建Windows服务项目

    (1)打开【Visual Studio】开发工具,然后选择【 Windows 服务(.NET Framework) 】,点击下一步。注意:Windows服务只有在.NET Framework版本中才有了,在跨平台中使用Worker Service。image.png(2)修改项目名称和项目存储目录,项目名称我写的是【MyDemoService】,然后框架我选择的是【.NET Farmework 4.8】,这个可以根据自己的需要填写和选择,然后点击【创建】。image.png创建好的目录如下:【Program.cs】是主程序的入口,【Service1.cs】是服务的入口,可以创建多个,然后在Prodrams.cs中配置就好了。image.png(3)【Service1】服务名称可以重命名修改,此处我重命名为【MyDemoService】, Program.cs文件中也相对应的也要进行修改。 image.pngimage.png(4)然后我们就可以在【MyDemoService】中写业务逻辑代码了,有很多种方式可以定位到要写的具体文件,先列举两种常用的。方法一:在【program.cs】文件中,找到这个类,按键盘上的F12可以直接进入查看文件。image.png方法二:直接右击,然后点击【查看代码】。image.png业务代码写到这里面:image.png到这一步服务就创建好了,然后就写具体的业务代码就行了。注意:服务必须至少重写 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】。image.png(2)【log4net.config】内容如下。

    
    
    	
    		
    	
    
    	
    		
    		
    	
    	
    		
    		
    		
    		
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    				
    				
    				
    
    				
    				
    				
    			
    			
    				
    				
    			
    		
    
    		
    		
    		
    		
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    				
    				
    				
    
    				
    				
    				
    			
    			
    				
    				
    			
    		
    
    
    		
    		
    		
    		
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    			
    				
    				
    				
    
    				
    				
    				
    			
    			
    				
    				
    			
    		
    
    		
    		
    			
    			
    			
    			
    			
    		
    	
    
    

    (3)并且右击【【log4net.config】】文件,点击【属性】,然后将[复制到输出目录]设置为【始终复制】。image.png(4)然后安装log4net。在项目目录中右击【引用】,然后点击【管理NuGet程序包】image.png(5)然后点击浏览,搜索【log4net】,右侧点击安装。image.png(6)重要:然后配置【AssemblyInfo.cs 】文件,如果不配置,是输出不了日志的。image.png添加到底部即可:(如果你的【log4net.config】文件路径和我的不一样,记得修改成跟自己配置路径一样的)。image.png代码:

    [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "config", ConfigFile = "LogConfig/log4net.config", Watch = true)]
    

    (7)然后就可以使用log4net了,首先在Windows服务中获得log4net的实例。image.png代码:

     private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    

    三、Windows服务的运行和部署

    3.1-服务基本配置

    (1)点击我们的服务【MyDemoService.cs】,然后右击点击【添加安装程序】。image.png(2)然后可以看到下面多出来了一个文件,就是安装程序。image.pngimage.png(3)然后可以修改基本信息,服务组件中的【服务名称】【服务描述】等等。我们右击【serviceInstall1】点击属性,然后进行修改。image.pngimage.png(4)然后点击【serviceProcessInstall1】右击属性,进行修改。image.pngimage.png

    3.2-服务运行与发布

    当我们直接按F5或者其他方式直接运行项目时,会提示:"无法从命令行或调试程序启动服务。必须首先安装 Windows服务(使用installutil.exe),然后用ServerExplorer、Windows服务管理工具或 NET START命令启动它。"。不是这样运行的,跟着下面步骤来操作运行与发布Windows服务吧。

    image.png

    前提注意:如果你设置的目标平台是x64,打开的目录会不一样,不然导致服务运行不起来。可以右击项目名,点击【属性】——>【生成】——>【目标平台】查看。image.png如果不是x64版本,复制这个地址:

    C:WindowsMicrosoft.NETFrameworkv4.0.30319

    如果是x64版本,复制这个地址:

    C:WindowsMicrosoft.NETFramework64v4.0.30319

    **不然会报类似这种错误:**在初始化安装时发生异常: System.BadImageFormatException: 未能加载文件或程序集...

    (1)然后我们把上面的地址(根据自己的环境选择)添加到环境变量中。点击【控制面板】——>【系统和安全】image.png(2)然后点击【系统】image.png(3)点击【高级系统设置】image.png(4)点击【环境变量】image.png(5)在【系统变量】中找到Path,然后点击【编辑】。image.png(6)然后点击【新建】,然后把我们拷贝的目录复制到这里。然后点击确认即可。image.png(7)测试是否配置成功,输入这个命令查看一下【InstallUtil】,如果是下面这样的内容说明成功了。image.png(8)然后编辑解决方案和项目。image.png(9)以管理员身份运行cmd命令,然后安装服务。

    InstallUtil 项目启动执行文件全路径
    西瓜程序猿的例子:
    InstallUtil D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe

    image.png(10)出现这个说明安装成功了。image.png(11)打开服务管理器,找到要启动的服务,然后右击启动服务。image.png启动后可以看到日志也有了:image.png(12)如果要卸载服务,可以运行这个命令:

    InstallUtil /u 项目启动执行文件全路径
    西瓜程序猿的例子:
    InstallUtil /u D:项目演示临时保存MyDemoServiceMyDemoServicebinDebugMyDemoService.exe

    image.png

    3.3-常见命令

    1、安装服务:InstallUtil 项目启动执行文件全路径
    3、启动服务:net start 服务名
    4、停止服务:net stop 服务名
    4、卸载服务:InstallUtil /u 项目启动执行文件全路径

    3.4-查看计算机事件

    如果在启动Windows服务时报错,我们可以通过查看计算机事件查询到具体的报错信息。

    (1)按键盘上的【Win+R】,然后输入【eventvwr.msc】image.png(2) 然后点击确定,就可以打开事件查看器的窗口。在窗口左侧找到【Windows日志】——>【系统】,就可以看到电脑的开机关机及日志记录了。image.png

    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
    

    截图:image.png

    四、高效工具:编写bat启动卸载服务

    4.1-安装服务

    我们可以创建一个文件【安装服务.bat】输入以下内容:

    chcp 65001
    REM Install
    InstallUtil 项目启动执行文件全路径
    pause
    

    注意:执行这个命令需要【以管理员身份】运行,不然会报这个错误:

    System.InvalidOperationException: 无法打开计算机“.”上的服务控制管理器。此操作可能需要其他特权。
    引发了内部异常 System.ComponentModel.Win32Exception,错误消息如下: 拒绝访问。。

    正确执行方式:image.png

    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…

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论