开发语言:C#

开发环境: Visual Studio 2022

微软官方文档:https://learn.microsoft.com/zh-cn/dotnet/framework/windows-services/

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

一、Windows服务概述

1.1-Windows服务是什么?

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

1.2-Windows能用来做什么?

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

1.3-Windows服务有什么优势?

  1. 后台执行:Windows服务在后台运行,不会干扰用户的工作,也无需用户登录即可持续执行任务。
  2. 系统级别权限:Windows服务可以在系统级别运行,具有更高的权限,可以访问系统资源和执行敏感操作。
  3. 自动启动:Windows服务可以在系统启动时自动启动,确保任务始终处于运行状态。
  4. 可靠性和稳定性: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-服务可以重写的方法

        /// <summary>
/// 服务启动:指示服务开始运行时应采取的操作。 必须在此过程中为服务编写代码才能执行有用的操作。
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
} /// <summary>
/// 服务停止:指示在服务停止运行时应发生什么情况。
/// </summary>
protected override void OnStop()
{
} /// <summary>
/// 暂停:指示在服务暂停时应发生什么情况。
/// </summary>
protected override void OnPause()
{
} /// <summary>
/// 继续:指示服务在暂停后恢复正常运行时应发生什么情况。
/// </summary>
protected override void OnContinue()
{
} /// <summary>
/// 停止前:指示在系统关闭之前应发生什么情况(如果此时服务正在运行)。
/// </summary>
protected override void OnShutdown()
{
}

2.3-配置日志(log4net)

为了方便测试,先介绍一下如何使用log4net做日志记录,当日志启动时和停止时我们记录一下。

(1)我们在项目目录下新建一个文件夹【LogConfig】,然后再创建一个文件为【log4net.config】。

(2)【log4net.config】内容如下。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections> <system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
<log4net>
<!--错误日志:::记录错误日志-->
<!--按日期分割日志文件 一天一个-->
<!-- appender 定义日志输出方式 将日志以回滚文件的形式写到文件中。-->
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
<!--保存路径:下面路径项目启动的时候自动在C盘中创建log、logError文件-->
<file value="log/error/error_" />
<!-- 如果想在本项目中添加路径,那就直接去掉C:\\ 只设置log\\LogError 项目启动中默认创建文件 -->
<appendToFile value="true"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date"/>
<!--这是按日期产生文件夹-->
<datePattern value="yyyy-MM-dd'.log'"/>
<!--是否只写到一个文件中-->
<staticLogFileName value="false"/>
<!--保留的log文件数量 超过此数量后 自动删除之前的 好像只有在 按Size分割时有效 设定值value="-1"为不限文件数-->
<param name="MaxSizeRollBackups" value="100"/>
<!--每个文件的大小。只在混合方式与文件大小方式下使用。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志-->
<maximumFileSize value="50MB" />
<!-- layout 控制Appender的输出格式,也可以是xml 一个Appender只能是一个layout-->
<layout type="log4net.Layout.PatternLayout">
<!--每条日志末尾的文字说明-->
<!--输出格式 模板-->
<!-- <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger
操作者ID:%property{Operator} 操作类型:%property{Action}%n 当前机器名:%property%n当前机器名及登录用户:%username %n
记录位置:%location%n 消息描述:%property{Message}%n 异常:%exception%n 消息:%message%newline%n%n" />--> <!--样例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info-->
<!--<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n错误描述:%message%newline %n"/>-->
<conversionPattern value="%n==========
%n【日志级别】%-5level
%n【记录时间】%date
%n【执行时间】[%r]毫秒
%n【出错文件】%F
%n【出错行号】%L
%n【出错的类】%logger 属性[%property{NDC}]
%n【错误描述】%message
%n【错误详情】%newline"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter,log4net">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
</appender> <!--DEBUG:::记录DEBUG日志-->
<!--按日期分割日志文件 一天一个-->
<!-- appender 定义日志输出方式 将日志以回滚文件的形式写到文件中。-->
<appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
<!--保存路径:下面路径项目启动的时候自动在C盘中创建log、logError文件-->
<file value="log/debug/debug_" />
<!-- 如果想在本项目中添加路径,那就直接去掉C:\\ 只设置log\\LogError 项目启动中默认创建文件 -->
<appendToFile value="true"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date"/>
<!--这是按日期产生文件夹-->
<datePattern value="yyyy-MM-dd'.log'"/>
<!--是否只写到一个文件中-->
<staticLogFileName value="false"/>
<!--保留的log文件数量 超过此数量后 自动删除之前的 好像只有在 按Size分割时有效 设定值value="-1"为不限文件数-->
<param name="MaxSizeRollBackups" value="100"/>
<!--每个文件的大小。只在混合方式与文件大小方式下使用。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志-->
<maximumFileSize value="50MB" />
<!-- layout 控制Appender的输出格式,也可以是xml 一个Appender只能是一个layout-->
<layout type="log4net.Layout.PatternLayout">
<!--每条日志末尾的文字说明-->
<!--输出格式 模板-->
<!-- <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger
操作者ID:%property{Operator} 操作类型:%property{Action}%n 当前机器名:%property%n当前机器名及登录用户:%username %n
记录位置:%location%n 消息描述:%property{Message}%n 异常:%exception%n 消息:%message%newline%n%n" />--> <!--样例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info-->
<!--<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n错误描述:%message%newline %n"/>-->
<conversionPattern value="%n==========
%n【日志级别】%-2level
%n【记录时间】%date
%n【执行时间】[%r]毫秒
%n【debug文件】%F
%n【debug行号】%L
%n【debug类】%logger 属性[%property{NDC}]
%n【debug描述】%message"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter,log4net">
<levelMin value="DEBUG" />
<levelMax value="WARN" />
</filter>
</appender> <!--INFO:::记录INFO日志-->
<!--按日期分割日志文件 一天一个-->
<!-- appender 定义日志输出方式 将日志以回滚文件的形式写到文件中。-->
<appender name="INFOAppender" type="log4net.Appender.RollingFileAppender">
<!--保存路径:下面路径项目启动的时候自动在C盘中创建log、logError文件-->
<file value="log/info/info_" />
<!-- 如果想在本项目中添加路径,那就直接去掉C:\\ 只设置log\\LogError 项目启动中默认创建文件 -->
<appendToFile value="true"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date"/>
<!--这是按日期产生文件夹-->
<datePattern value="yyyy-MM-dd'.log'"/>
<!--是否只写到一个文件中-->
<staticLogFileName value="false"/>
<!--保留的log文件数量 超过此数量后 自动删除之前的 好像只有在 按Size分割时有效 设定值value="-1"为不限文件数-->
<param name="MaxSizeRollBackups" value="100"/>
<!--每个文件的大小。只在混合方式与文件大小方式下使用。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志-->
<maximumFileSize value="50MB" />
<!-- layout 控制Appender的输出格式,也可以是xml 一个Appender只能是一个layout-->
<layout type="log4net.Layout.PatternLayout">
<!--每条日志末尾的文字说明-->
<!--输出格式 模板-->
<!-- <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger
操作者ID:%property{Operator} 操作类型:%property{Action}%n 当前机器名:%property%n当前机器名及登录用户:%username %n
记录位置:%location%n 消息描述:%property{Message}%n 异常:%exception%n 消息:%message%newline%n%n" />--> <!--样例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info-->
<!--<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n错误描述:%message%newline %n"/>-->
<conversionPattern value="%n==========
%n【日志级别】%-2level
%n【记录时间】%date
%n【执行时间】[%r]毫秒
%n【info文件】%F
%n【info行号】%L
%n【info类】%logger 属性[%property{NDC}]
%n【info描述】%message"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter,log4net">
<levelMin value="INFO" />
<levelMax value="WARN" />
</filter>
</appender> <!--Set root logger level to DEBUG and its only appender to A1-->
<root>
<!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
<level value="ALL" />
<appender-ref ref="DebugAppender" />
<appender-ref ref="ErrorAppender" />
<appender-ref ref="INFOAppender" />
</root>
</log4net>
</configuration>

(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:\Windows\Microsoft.NET\Framework\v4.0.30319

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

C:\Windows\Microsoft.NET\Framework64\v4.0.30319

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

(1)然后我们把上面的地址(根据自己的环境选择)添加到环境变量中。点击【控制面板】——>【系统和安全】

(2)然后点击【系统】

(3)点击【高级系统设置】

(4)点击【环境变量】

(5)在【系统变量】中找到Path,然后点击【编辑】。

(6)然后点击【新建】,然后把我们拷贝的目录复制到这里。然后点击确认即可。

(7)测试是否配置成功,输入这个命令查看一下【InstallUtil】,如果是下面这样的内容说明成功了。

(8)然后编辑解决方案和项目。

(9)以管理员身份运行cmd命令,然后安装服务。

InstallUtil 项目启动执行文件全路径

西瓜程序猿的例子:

InstallUtil D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe


(10)出现这个说明安装成功了。

(11)打开服务管理器,找到要启动的服务,然后右击启动服务。

启动后可以看到日志也有了:

(12)如果要卸载服务,可以运行这个命令:

InstallUtil /u 项目启动执行文件全路径

西瓜程序猿的例子:

InstallUtil /u D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.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服务的多个实例

这个方案比较全可以参考:https://www.u72.net/b/show-317328.html

我是西瓜程序猿,用的是这种方法:
(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:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe 程序集的进度。

该文件位于 D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.InstallLog。

正在回滚程序集“D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe”。

受影响的参数是:

logtoconsole =

logfile = D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.InstallLog

assemblypath = D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe

正在将事件日志还原到源 TestDemoServices 的前一状态。

“回退”阶段已成功完成。

已完成事务处理安装。

安装失败,已执行回退。

解决:权限不够,打开cmd时记得【以管理员身份】打开。

2、未能加载文件或程序集xxx的基个依赖项

在初始化安装时发生异常: System.BadImageFormatException: 未能加载文件或程序集“file://E:\DebuginServers.sB惑的基个依赖项。试图加载格式不正确的程序。

解决:请看本文第【3.2】点

3、在执行【.bat】文件时,报路径不存在相关的错

** 执行命令**:InstallUtil /u D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe

错误信息:C:\Windows\system32>InstallUtil /u D:\椤圭洰婕旂ず涓存椂淇濆瓨\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe Microsoft (R) .NET Framework 安装实用工具版本 4.8.9037.0 版权所有 (C) Microsoft Corporation。保留所有权利。 在初始化安装时发生异常: System.IO.FileNotFoundException: 未能加载文件或程序集“file:///D:\椤圭洰婕旂ず涓存椂淇濆瓨\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe”或它的某一个依赖项。系统找不到指定的文件。。

分析:这个错是乱码导致的,执行的命令是这个【InstallUtil /u D:\项目演示临时保存\MyDemoService\MyDemoService\bin\Debug\MyDemoService.exe】,但是在控制台里面显示的是这个【file:///D:\椤圭洰婕旂ず涓存椂淇濆瓨\MyDemoService\MyDemoService\bin\Debug\MyDemoService.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

原文链接:https://www.cnblogs.com/kimiliucn/p/17637533.html

使用C#创建安装Windows服务程序(最全教程)的更多相关文章

  1. .NET 跨平台RPC框架DotNettyRPC Web后台快速开发框架(.NET Core) EasyWcf------无需配置,无需引用,动态绑定,轻松使用 C# .NET 0配置使用Wcf(半成品) C# .NET Socket 简单实用框架 C# .NET 0命令行安装Windows服务程序

    .NET 跨平台RPC框架DotNettyRPC   DotNettyRPC 1.简介 DotNettyRPC是一个基于DotNetty的跨平台RPC框架,支持.NET45以及.NET Standar ...

  2. 创建一个Windows服务程序与实现定时器效果

    1.创建一个Windows服务程序 一.   新建Window服务项目 二.   添加安装程序 三.   配置服务属性 四.   编写定时器代码 publicpartialclassService1 ...

  3. C# .NET 0命令行安装Windows服务程序

    设计原则:万物皆对象 背景:在我的项目中,即需要与硬件通过Socket连接通讯,又需要给App提供Wcf服务操作接口,虽然都完成了,但是却是一个控制台(虽然我很喜欢控制台,因为它简单易用),把它放到服 ...

  4. 使用windows api安装windows服务程序(C#)

    3个步骤: 1.安装器代码编写 2.安装器工具类编写 1)安装.启动服务) 2)卸载服务 3.windows服务程序编写(参考:多线程.方便扩展的Windows服务程序框架) 4.代码下载,在文末(注 ...

  5. Mac安装Windows 10的简明教程

    每次在Mac上安装Windows都是一件非常痛苦的事情,曾经为了装Win8把整台Mac的硬盘数据都弄丢了,最后通过龟速系统恢复模式恢复了MacOSX(50M电信光纤下载了3天才把系统下载完),相信和我 ...

  6. [react]react创建app,路由,mobx 全教程

    ​ 1.创建app, npx create-react-app my-app Cmd Copy 2.进入项目目录 cd my-app Cmd Copy 3.启用配置文件(默认是不开启配置文件的) ya ...

  7. 用Visual C#创建Windows服务程序

    一.Windows服务介绍: Windows服务以前被称作NT服务,是一些运行在Windows NT.Windows 2000和Windows XP等操作系统下用户环境以外的程序.在以前,编写Wind ...

  8. 最简单的C# Windows服务程序

    通过这个示例了解如何通过C#如何创建一个Windows服务程序. 工具/原料   Vistual Studio 2015 c# 方法/步骤     打开vs2015 文件->新建项目->V ...

  9. .net Windows服务程序和安装程序制作图解 及 VS 2010创建、安装、调试 windows服务(windows service)

    .net Windows服务程序和安装程序制作 最近项目中用到window服务程序,以前没接触过,比较陌生,花了两天的时间学习了下,写了个简单的服务,但在制作安装程序的时候,参照网上很多资料,却都制作 ...

  10. C#/.NET基于Topshelf创建Windows服务程序及服务的安装和卸载(极速,简洁)

    本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...

随机推荐

  1. 2020-11-06:go中,谈一下调度器。

    福哥答案2020-11-06:·MPG模型:goroutine的并发模型可以归纳为MPG模型:·MPG概念:线程(machine,系统线程,物理线程)-内核(processor)-协程(gorouti ...

  2. 问题解决:TNS-12543: TNS:destination host unreachable

    环境: 11.2.0.3 ADG (db11g\db11gadg\db11gcas) 在自己先前克隆后的环境互相tnsping报错. tnsping 本机ok,tnsping其他机器均报错: [ora ...

  3. Java JDK1.8环境变量配置

    Java JDK1.8.0_152下载地址:https://pan.baidu.com/s/1BRB2MRETPdWVL-IN2FRTEw   提取码:63jb 下载好后傻瓜式一键Next下载就好,默 ...

  4. 文心一言 VS 讯飞星火 VS chatgpt (28)-- 算法导论5.1 3题

    三.假设你希望以1/2的概率输出0与 1.你可以自由使用一个输出0或1的过程 BIASED-RANDOM.它以某概率 p 输出1,概率 1-p 输出0,其中 0<p<1 ,但是 p 的值未 ...

  5. JSON第二

    HTML DOM 节点在 HTML DOM 中,所有事物都是节点.DOM 是被视为节点树的 HTML. TML 文档中的所有内容都是节点:整个文档是一个文档节点每个 HTML 元素是元素节点HTML ...

  6. 非 root 用户手动编译安装 GCC

    我们知道,关于 GCC 在 CentOS 下通过 yum 安装默认版本号,CentOS 5 是 4.1.2:CentOS 6 是 4.4.7:CentOS 7 是 4.8.3.很多时候在编译安装软件都 ...

  7. uniapp主题切换功能的方式终结篇(全平台兼容)

    前面我已经给大家介绍了两种主题切换的方式,每种方式各有自己的优势与缺点,例如"scss变量+vuex"方式兼容好但不好维护与扩展,"scss变量+require" ...

  8. SpringBoot之MVC配置(WebMvcConfigurer详解)

    一:基本介绍 Spring MVC是一种常用的Java Web框架,它提供了一种基于MVC模式的开发方式,可以方便地实现Web应用程序.在Spring MVC中,WebMvcConfigurer是一种 ...

  9. HLS AES加密

    HLS AES加密 HLS AES加密介绍 HLS AES加密是一种用于保护HLS流内容安全的加密技术.它通过将HLS媒体文件进行分段,并使用AES加密算法对每个片段进行加密,从而防止未经授权的访问和 ...

  10. ##Can not deserialize instance of java.lang.String out of START_OBJECT token

    请求中定义了一个String字段,该字段主要是一个JSON Object字符串,对应的Java PO的相关字段类型是String. 但是测试的时候传的参数是JSON对象,例如{"aa&quo ...