关于使用Topshelf创建服务
0. 背景说明
我为什么要创建windows服务?因为有一个操作需要我定时执行,这个操作可以是定时的数据同步或是周期性的某种操作
之前都是按照以下方式实现的:
若是数据库层面定时任务,则创建一个定时作业
其他操作,则创建一个控制台程序,使用windows服务自带的任务计划程序,定时周期性执行该控制台程序
而目前出现了问题:
数据库作业,因为我使用的数据库账号没有看不到“SQL Server代理”,就是没有权限创建作业
控制台程序因为引用其他的dll文件所以偶尔出现被杀毒软件删除,需要加入白名单。但也意味着其不够健壮。
1. 使用Topshelf组件创建Windows服务
使用Topshelf可以便捷的创建一个Windows服务
该组件可以通过创建一个控制台程序,实现一个windows服务
该组件可以配合Log4net和Quartz.net实现记录日志和定时执行
Nuget:
Install-Package Topshelf -Version 4.3.0
Install-Package Topshelf.Log4Net -Version 4.3.0(注:依赖于Log4net)
Install-Package Topshelf.Quartz -Version 0.4.0.1(注:依赖于Quartz)
1.1 依赖Quartz.net实现定时任务
定义任务类,实现Ijob接口
//using log4net;
//using Quartz;
/// <summary>
/// 任务类,定义我们需要调度的任务
/// </summary>
public class MyJob : IJob
{
private readonly ILog _logger = LogManager.GetLogger(typeof(MyJob));
public void Execute(IJobExecutionContext context)
{
//todo:你所期望实现定时执行的操作
//计入日志
_logger.InfoFormat("任务执行成功");
}
}
简单的安装单例模式封装一个调度器类,
这里调度规则简单示例为每隔5s执行一次
//using Quartz;
//using Quartz.Impl;
/// <summary>
/// 任务调度器类,用于创建调度器并配置调度计划
/// </summary>
public class MyScheduler
{
private static readonly MyScheduler myScheduler = new MyScheduler();
//调度器
public IScheduler scheduler { private set; get; }
//任务
public IJobDetail job { private set; get; }
//触发器
public ISimpleTrigger trigger { private set; get; }
private MyScheduler()
{
scheduler = StdSchedulerFactory.GetDefaultScheduler();
job = JobBuilder.Create<MyJob>().Build();
trigger = TriggerBuilder.Create()
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever())//配置每隔5s执行一次,永久执行下去
.WithIdentity("trigger", "group").Build() as ISimpleTrigger;
scheduler.ScheduleJob(job, trigger);
}
//单例模式,用于返回单例对象
public static MyScheduler GetMyScheduler()
{
return myScheduler;
}
}
1.2 依赖于Topshelf创建服务类
//using Quartz;
//using Topshelf;
/// <summary>
/// 服务类,实现相应接口,定义服务启动和停止执行的操作
/// </summary>
public class MyServiceRunner : ServiceControl, ServiceSuspend
{
private readonly IScheduler scheduler = MyScheduler.GetMyScheduler().scheduler;
#region ServiceControl接口需要实现的方法
public bool Start(HostControl hostControl)
{
scheduler.Start();
return true;
}
public bool Stop(HostControl hostControl)
{
scheduler.Shutdown(false);
return true;
}
#endregion
#region ServiceSuspen接口需要实现的方法
public bool Continue(HostControl hostControl)
{
scheduler.ResumeAll();
return true;
}
public bool Pause(HostControl hostControl)
{
scheduler.PauseAll();
return true;
}
#endregion
}
1.3 log4net的配置文件log4net.config
这里通过配置将日志信息写入到数据库中
- 日志表建表语句
CREATE TABLE [dbo].[Log4net] (
[Id] [int] IDENTITY (1, 1) NOT NULL,
[Date] [datetime] NOT NULL,
[Thread] [varchar] (255) NOT NULL,
[Level] [varchar] (50) NOT NULL,
[Logger] [varchar] (255) NOT NULL,
[Message] [varchar] (4000) NOT NULL,
[Exception] [varchar] (2000) NULL
)
- 注意数据库的连接字符串需要单独写在项目的配置文件中
- 右键log4net.config-->属性-->复制的输出目录:始终复制
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- ...................................为Log4Net添加的配置.....开始.................................-->
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<root>
<level value="ALL"></level>
<appender-ref ref="AdoNetAppender"></appender-ref>
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection,System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionStringName value="ConnectionStringLogging" />
<commandText value="INSERT INTO Log4net ([Date],[Thread],[Level],[Logger],[Message],[Exception])
VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
</log4net>
</configuration>
1.4 主函数中配置服务信息
static void Main(string[] args)
{
//这里读取log4net.config
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomainBaseDirectory + "log4net.config"));
HostFactory.Run(x =>
{
x.UseLog4Net();
x.Service<MyServiceRunner>();
x.SetDescription("服务描述");
x.SetDisplayName("服务显示名称");
x.SetServiceName("服务名称");
x.EnablePauseAndContinue();
});
}
1.5 安装服务
编译后得到的控制台程序 xxx.exe,
以管理员的身份运行命令行程序,跳转到程序所在路径,执行该命令
xxx.exe install
win+R:services.msc 打开服务管理器,找到安装的服务并右键启动
找到自己安装的服务,可以右键属性设置其他一些功能,如服务失败后的操作等
卸载该服务,则先在停止,在按照安装的方法,管理员身份打开命令行,跳转程序路径,执行
xxx.exe uninstall
3. Demo源码下载及参考文档
若是简单的周期执行,也可以不使用Quartz .net ,而是使用System.Timers.Timer对象实现间隔一定的时间执行一次任务
而且可以抛弃Log4net,只是简单的使用 System.IO.StreamWriter在服务本地简单的记录一个日志文本
该功能就是Topshelf官方文档中的最简的入门示例
关于使用Topshelf创建服务的更多相关文章
- [Solution] Microsoft Windows 服务(2) 使用Topshelf创建Windows服务
除了通过.net提供的windows服务模板外,Topshelf是创建Windows服务的另一种方法. 官网教程:http://docs.topshelf-project.com/en/latest/ ...
- 使用Topshelf创建Windows服务
概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...
- Topshelf创建Windows服务
使用Topshelf创建Windows服务 概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps ...
- C#/.NET基于Topshelf创建Windows服务程序及服务的安装和卸载(极速,简洁)
本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...
- windowsSevice程序和topshelf程序创建服务对比
文章原地址:http://www.80iter.com/blog/1451523192435464 Topshelf 创建.net服务整理和安装步骤 windowsService和topshelf服务 ...
- 【第三方插件】使用Topshelf创建Windows服务
概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...
- C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案
本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...
- 使用Topshelf创建Windows服务[转载]
概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...
- WIN32服务程序(一):创建服务
MSDN中有安装服务的例子Installing a Service(可点击进入),我们这里的创建服务,和MSDN里的例子基本上是一样的.这里做一些简单的说明: 打开控制面板,管理工具,服务.我们看到的 ...
随机推荐
- python3排序 sorted(key=lambda)--实现对字典按value值排序
使用python对列表(list)进行排序,说简单也简单,说复杂也复杂,我一开始学的时候也搞不懂在说什么,只能搜索一些英文文章看看讲解,现在积累了一些经验,写在这里跟大家分享, 1.sorted函数首 ...
- 菜鸡的Java笔记 comparator 比较器
1.数组操作类: Arrays 2.两种比较器的使用: Comparable Comparator 3.实现二叉树算法 content (内容) ...
- [bzoj2743]采花
预处理出每一个点下一个相同颜色的位置,记为next,然后将询问按左端点排序后不断右移左指针,设要删除i位置,就令f[next[next[i]]+1,同时还要删除原来的标记,即令f[next[i]]-1 ...
- Java安全之Axis漏洞分析
Java安全之Axis漏洞分析 0x00 前言 看到个别代码常出现里面有一些Axis组件,没去仔细研究过该漏洞.研究记录一下. 0x01 漏洞复现 漏洞版本:axis=<1.4 Axis1.4 ...
- 程序员需要达到什么水平才能顺利拿到 20k 无压力?
程序员要拿到20k,应该达到什么水平? 1 熟悉增删改查技能,熟悉项目开发相关流程和技能. 2 能解决基本问题,分布式或比较深的问题,太难的不会不要紧,但常规的应该有项目经验. 3 简历好看些 ...
- 重新整理 .net core 实践篇——— 权限中间件源码阅读[四十六]
前言 前面介绍了认证中间件,下面看一下授权中间件. 正文 app.UseAuthorization(); 授权中间件是这个,前面我们提及到认证中间件并不会让整个中间件停止. 认证中间件就两个作用,我们 ...
- Hi3516开发笔记(五):通过HiTools使用网口将uboot、kernel、roofts和userdata按照分区表烧写镜像
前言 前面生成了uboot,kernel,sample,userdata(我们实际修改了ip的),rootfs,现在需要烧写进入核心板. 使用网口烧写镜像(海思烧写必须占用调试串口) 步骤一: ...
- Java 中的监控与管理原理概述
点赞再看,动力无限.Hello world : ) 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 程序猿阿朗博客 已经收录,有很多知识点和系列文章. 当前 ...
- javaSE基础复习
第一天:复习java入门知识,jvm内存,java程序执行流程,数据类型,变量和自动类型转换,运算符... 学习java目的:起初是因为想找工作,拿高薪.后来逐渐在学习java技术的过程中渐渐循喜欢上 ...
- Codeforces 1383F - Special Edges(状态压缩+最大流)
Codeforces 题目传送门 & 洛谷题目传送门 首先暴力显然是不行的,如果你暴力最大流过了我请你吃糖 注意到本题的 \(k\) 很小,考虑以此为突破口解题.根据最大流等于最小割定理,点 ...