这也是看网上的例子自己跟着配置做的一个小demo,这里记录一下。

一、创建一个空的控制台应用程序

二、安装所需dll 

  1.Quartz 
    Install-Package Quartz -Version 2.3.3
  2.Owin
    Install-Package Owin -Version 1.0.0(这个暂时装上)
  3.TopShelf
    Install-Package TopShelf -Version 3.3.1
  4.log4net
    Install-Package log4net -Version 2.0.8
  5.TopShelf.log4net
    Install-Package Topshelf.Log4Net -Version 3.3.1

这里我把版本都标记出来是因为NuGet安装的时候有可能最新的版本会不兼容的问题,如果出现请降版本安装。

三、手动创建

  1.log4net.config

  

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections> <log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<!--日志路径-->
<param name= "File" value= "Log\"/>
<!--是否是向文件中追加日志-->
<param name= "AppendToFile" value= "true"/>
<!--log保留天数-->
<param name= "MaxSizeRollBackups" value= ""/>
<!--日志文件名是否是固定不变的-->
<param name= "StaticLogFileName" value= "false"/>
<!--日志文件名格式为:--.log-->
<param name= "DatePattern" value= "yyyy-MM-dd&quot;.read.log&quot;"/>
<!--日志根据日期滚动-->
<param name= "RollingStyle" value= "Date"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date{HH:mm:ss,fff} %-5p-%m%n" />
</layout>
</appender> <!-- 控制台前台显示日志 -->
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR" />
<foreColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="Info" />
<foreColor value="Green" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
</layout> <filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="Info" />
<param name="LevelMax" value="Fatal" />
</filter>
</appender> <root>
<!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) -->
<level value="all" />
<appender-ref ref="ColoredConsoleAppender"/>
<appender-ref ref="RollingLogFileAppender"/>
</root> </log4net>
</configuration>

  2.quartz.config

# You can configure your scheduler in either <quartz> configuration section
# or in quartz properties file
# Configuration section has precedence quartz.scheduler.instanceName = QuartzTest # configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount =
quartz.threadPool.threadPriority = Normal # job initialization plugin handles our xml reading, without it defaults are used
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml # export this server to remoting context
#quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
#quartz.scheduler.exporter.port =
#quartz.scheduler.exporter.bindName = QuartzScheduler
#quartz.scheduler.exporter.channelType = tcp
#quartz.scheduler.exporter.channelName = httpQuartz

  3.quartz_jobs.xml

<?xml version="1.0" encoding="utf-8" ?>
<!-- This file contains job definitions in schema version 2.0 format --> <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"> <processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives> <schedule> <!--TestJob测试 任务配置 -->
<job>
<name>TestJob</name>
<group>Test</group>
<description>TestJob测试</description>
<job-type>HostProject.QuartzJobs.TestJob,HostProject</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<trigger>
<cron>
<name>TestJobTrigger</name>
<group>Test</group>
<job-name>TestJob</job-name>
<job-group>Test</job-group>
<!-- 从start-time起,每5s执行一次IJob.Execute -->
<start-time>--22T00::+:</start-time>
<cron-expression>/ * * * * ?</cron-expression>
</cron>
</trigger> </schedule>
</job-scheduling-data>

四、创建 ServiceRunner.cs

 public class ServiceRunner : ServiceControl, ServiceSuspend
{
private readonly IScheduler _IScheduler;
public ServiceRunner()
{
_IScheduler = StdSchedulerFactory.GetDefaultScheduler();
}
public bool Start(HostControl hostControl)
{
_IScheduler.Start();
return true;
} public bool Stop(HostControl hostControl)
{
_IScheduler.Shutdown();
return true;
} public bool Continue(HostControl hostControl)
{
_IScheduler.ResumeAll();
return true;
} public bool Pause(HostControl hostControl)
{
_IScheduler.PauseAll();
return true;
}
}

五、TestJob

  public sealed class TestJob:IJob
{
public void Execute(IJobExecutionContext context)
{
CommonHelper.AppLogger.InfoFormat("TestJob测试");
try
{ //模拟调用存储过程,更新商品库存 string connStr = "Data Source=.;Initial Catalog=test;User Id=sa;Password=p@ss!123;"; using (SqlConnection conn = new SqlConnection(connStr))
{ using (SqlCommand cmd = new SqlCommand())
{ conn.Open(); cmd.Connection = conn; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "proc_UpdateInventory"; Random random = new Random(); SqlParameter[] paras = new SqlParameter[] { new SqlParameter() { ParameterName = "@GoodsId", SqlDbType = SqlDbType.Int, Value = random.Next(, ) }, new SqlParameter() { ParameterName = "@Inventory", SqlDbType = SqlDbType.Int, Value = random.Next(, ) } }; cmd.Parameters.AddRange(paras); int rowCount = cmd.ExecuteNonQuery(); //exec proc_UpdateInventory @GoodsId=1,@Inventory=25 if (rowCount > ) CommonHelper.AppLogger.InfoFormat("商品:{0},库存已更新,新的库存为:{1}", paras[].Value, paras[].Value); else CommonHelper.AppLogger.InfoFormat("更新商品库失败,无受影响记录:{0}", rowCount); } } } catch (Exception ex)
{ CommonHelper.AppLogger.ErrorFormat("UpdateInventoryJob 作业执行异常:{0}", ex); }
}
}

六、CommonHelper

  class CommonHelper
{
public static readonly ILog AppLogger = log4net.LogManager.GetLogger("ColoredConsoleAppender");
static CommonHelper() { }
}

七、Program中代码调用

 static void Main(string[] args)
{
XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config")); HostFactory.Run(x => {
x.UseLog4Net();
x.Service<ServiceRunner>();
x.RunAsLocalSystem(); x.SetDescription("Quartz+TopShelf实现Windows服务作业调度的一个示例Demo");
x.SetDisplayName("QuartzTopShelfDemo服务");
x.SetServiceName("QuartzTopShelfDemoService"); x.EnablePauseAndContinue(); });
}

八、特别注意

这三个文件手动创建,默认是“不复制”,这里需要修改为“始终复制”

这样一个Host便可以运行起来了。

九、安装到Windows

用cmd命令行打开这个文件夹

执行命令  : HostProject.exe install

卸载:HostProject.exe uninstall

十、SQL脚本(先把存储过程执行过在运行项目)

IF ( OBJECT_ID('Goods', 'U') IS NOT NULL )
DROP TABLE Goods; GO CREATE TABLE Goods
(
Id INT IDENTITY(1, 1)
NOT NULL ,
Name NVARCHAR(30) NOT NULL ,
Inventory INT
NOT NULL
CONSTRAINT PK_Goods_Id PRIMARY KEY CLUSTERED ( Id ASC ) ON [PRIMARY]
)
ON [PRIMARY]; INSERT INTO Goods
VALUES ( '大米', 0 ),
( '香蕉', 0 ),
( '苹果', 0 ); SELECT *
FROM Goods; IF ( OBJECT_ID('proc_UpdateInventory', 'P') IS NOT NULL )
DROP PROCEDURE proc_UpdateInventory; GO CREATE PROCEDURE proc_UpdateInventory
(
@GoodsId INT ,
@Inventory INT
)
AS
UPDATE Goods
SET Inventory = @Inventory
WHERE Id = @GoodsId; GO

十一、说明

  这里没有对使用进行说明,还有Owin的还没用,后面有时间会补上。

十二、效果

Host服务的更多相关文章

  1. .NET Core Generic Host Windows服务部署使用Topshelf

    此文源于前公司在迁移项目到.NET Core的过程中,希望使用Generic Host来管理定时任务程序时,没法部署到Windows服务的问题,而且官方也没给出解决方案,只能关注一下官方issue # ...

  2. 利用Topshelf把.NET Core Generic Host管理的应用程序部署为Windows服务

    背景 2019第一篇文章. 此文源于前公司在迁移项目到.NET Core的过程中,希望使用Generic Host来管理定时任务程序时,没法部署到Windows服务的问题,而且官方也没给出解决方案,只 ...

  3. (转)解决 ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务

    下面操作默认在安装Oralce数据库的服务器上运行. 1)确保Oracle 基本服务都已启动 OracleDBConsoleorcl OracleOraDb11g_home1TNSListener O ...

  4. 使用Topshelf创建Windows服务

    概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...

  5. WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发

    今天我们继续WCF分布式开发步步为赢(3)WCF服务元数据交换.配置及编程开发的学习.经过前面两节的学习,我们了解WCF分布式开发的相关的基本的概念和自定义宿主托管服务的完整的开发和配置过程.今天我们 ...

  6. Topshelf创建Windows服务

    使用Topshelf创建Windows服务 概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps ...

  7. win7老是弹出“Windows Media PIayer网络共享服务配置应用程序 已停止工作”

    应是优化软件的时候把服务禁止启动了. 我的电脑 > 管理 > 服务和应用程序 > 服务 Windows Media Player Network Sharing Service 启动 ...

  8. 使用“消息服务框架”(MSF)实现分布式事务的三阶段提交协议(电商创建订单的示例)

    1,示例解决方案介绍 在上一篇 <消息服务框架(MSF)应用实例之分布式事务三阶段提交协议的实现>中,我们分析了分布式事务的三阶段提交协议的原理,现在我们来看看如何使用消息服务框架(MSF ...

  9. Bumblebee微服务网关的部署和扩展

    Bumblebee是.netcore下开源基于BeetleX.FastHttpApi扩展的HTTP微服务网关组件,它的主要作用是针对WebAPI集群服务作一个集中的转发和管理:作为应用网关它提供了应用 ...

随机推荐

  1. 【Gym - 100923I】Por Costel and the Pairs(思维题)

    Por Costel and the Pairs Descriptions 有T组测试样例 有n个男的,n个女的,第i个人都有为当前一个大小为i的懒惰值,当一男一女懒惰值的乘积<=n他们就就可以 ...

  2. Linux远程开发

    Linux远程开发 通常,当我们开发Linux程序时有两种方案: 在Linux上直接编写程序并进行运行测试和调试 在Windows或Mac OS X上借助工具进行远程开发 虽然我自己是在Linux环境 ...

  3. Guava源码阅读-io-Files

    package com.google.common.io; 今天阅读一个非常常用的类Files,文件操作类. readLines(File file, Charset charset),这个方法将Fi ...

  4. centos7 的system

    1.vim /etc/systemd/system/alertmanager.service [Unit] Description=Alertmanager After=network-online. ...

  5. 用elasticsearch分析中国大学省份分布

    1.去教育部官网下载excel数据:http://www.moe.gov.cn/srcsite/A03/moe_634/201706/W020170616379651135432.xls 2.把xls ...

  6. 浅谈 OpenResty,基于opebresty+redis进行实时线上限流

    一.前言 我们都知道Nginx有很多的特性和好处,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开 ...

  7. PYTHON 100days学习笔记008-1:数据结构补充

    目录 Day008_01:数据结构补充 1.列表list 1.1 将列表当作堆栈使用 1.2 将列表当作队列使用 1.3 列表推导式 1.4 嵌套列表解析 1.5 del语句 2.元组和序列 3.集合 ...

  8. Node KOA框架入门

    KOA: v1 generator v2 过渡版 generator&async v3 async/await koa koa不带路由 因此得cnpm i koa-router -D 路由:1 ...

  9. 查询list转化为tree的两种方式及排序

    方式一,数据库查询tree; MyBatis collection 集合 MyBatis 是数据持久层框架,支持定制化 SQL.存储过程以及高级映射.尤其强大在于它的映射语句,比如高级映射中的 col ...

  10. [转帖]中芯国际14nm秋季量产 7nm工艺或在2020年底问世

    中芯国际14nm秋季量产 7nm工艺或在2020年底问世 https://news.mydrivers.com/1/641/641087.htm 中芯正在发力.. 今年秋天 14nm两场 明年底 7n ...