引言

  现在许多的项目都需要定时的服务进行支撑,而我们经常用到的定时服务就是Quartz任务调度了。不过我们在使用定时Job进行获取的时候,有时候我们就需要记录一下自定义的日志,甚至我们还会对执行定时Job脚本中,本身的线程启动和触发器等相关信息进行记录,这就用到了Common.Logging.log4net了,但同时它在控制台上输出相应信息的同时,并不能对这些信息进行日志文件的记录与存储。

  有关log4net的相关使用,详情请看之前的博文:http://www.cnblogs.com/huanghzm/p/4754890.html

  而本文的主要目的就是处理Quartz系统日志与log4net的相互结合,最后附带说明了利用Topshlef坐直windows服务。

准备

  1、安装指定的程序包

  Install-Package Quartz

  Install-Package Common.Logging.Log4Net1211(安装这个的时候会自定安装其依赖项,即Log4Net)

  Install-Package Topshelf

  2、配置文件设置

<configSections>
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections> <common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1211">
<arg key="configType" value="INLINE" />
</factoryAdapter>
</logging>
</common> <log4net>
<!--错误日志-->
<!--自定义错误异常-->
<appender name="CustomExAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\\LogCustomEx\\" />
<param name="AppendToFile" value="true" />
<param name="MaxFileSize" value="" />
<param name="MaxSizeRollBackups" value="" />
<param name="StaticLogFileName" value="false" />
<param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
<param name="RollingStyle" value="Date" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
</layout>
</appender> <appender name="ErrorExAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\\LogErrorEx\\" />
<param name="AppendToFile" value="true" />
<param name="MaxFileSize" value="" />
<param name="MaxSizeRollBackups" value="" />
<param name="StaticLogFileName" value="false" />
<param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
<param name="RollingStyle" value="Date" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
</layout>
</appender> <!--CustomEx日志-->
<logger name="LogCustomEx">
<level value="INFO" />
<appender-ref ref="CustomExAppender" />
</logger>
<!--Error日志-->
<logger name="LogErrorEx">
<level value="ERROR" />
<appender-ref ref="ErrorExAppender" />
</logger> <!--服务执行日志-->
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\\ServerLog\\" />
<param name="AppendToFile" value="true" />
<param name="MaxFileSize" value="" />
<param name="MaxSizeRollBackups" value="" />
<param name="StaticLogFileName" value="false" />
<param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
<param name="RollingStyle" value="Date" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
</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>

App.Config

让世界跑起来

  1、配置相关Job类(JobInfo[对象]、JobType[类型]、JobInfoList[触发器、时间]) 名称、触发器、群组、类型(根据不同的类型执行不同的Job内容)

public class JobInfo
{
public JobInfo(string jobName, string group, string trigger, JobType jobType)
{
if (jobName == null || trigger == null || group == null)
{
throw new ArgumentNullException("jobName");
}
this.JobName = jobName;
this.Trigger = trigger;
this.Group = group;
this.JobType = jobType;
} /// <summary>
/// 名称
/// </summary>
public string JobName { get; set; } /// <summary>
/// Job的触发器 cron表达式
/// </summary>
public string Trigger { get; set; } /// <summary>
/// 群组
/// </summary>
public string Group { get; set; } /// <summary>
/// Job类型
/// </summary>
public JobType JobType { get; set; }
} /// <summary>
/// Job类型枚举
/// </summary>
public enum JobType
{
/// <summary>
/// 任务1
/// </summary>
Job1 = ,
/// <summary>
/// 任务2
/// </summary>
Job2 =
}

JobInfo

public class JobInfoList
{
/// <summary>
/// 脚本服务组
/// </summary>
public static List<JobInfo> JobList_ZhongShanHos = new List<JobInfo>
{
new JobInfo("任务1", "测试脚本", "*/5 * * * * ?", JobType.Job1),
new JobInfo("任务2", "测试脚本", "*/7 * * * * ?", JobType.Job2) };
}

JobInfoList

  2、配置具体的Job内容与需要输出的自定义日志,这里的日志使用log4net作为记录 (TestJob.cs)

public class TestJob : IJob
{
private static readonly log4net.ILog LogInfo = log4net.LogManager.GetLogger("LogCustomEx");
private static readonly log4net.ILog LogError = log4net.LogManager.GetLogger("LogError"); public void Execute(IJobExecutionContext context)
{
var map = context.JobDetail.JobDataMap;
var jobInfo = map["KEY"] as JobInfo;
if (jobInfo == null) { return; } //记录日志
LogInfo.Info("\n【服务已启动】" + "\n【启动组】:" + jobInfo.Group + "\n【启动名称】:" + jobInfo.JobName + "\n【启动时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); try
{
switch (jobInfo.JobType)
{
//基础信息
case JobType.Job1: LogInfo.Info("这是任务1"); break;
case JobType.Job2: LogInfo.Info("这是任务2"); break; default: break;
}
}
catch (Exception ex)
{
//记录日志
LogError.Error("\n【服务执行出错】" +
"\n【启动组】:" + jobInfo.Group +
"\n【启动名称】:" + jobInfo.JobName +
"\n【时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") +
"\n【错误信息】:" + ex.Message);
return;
}
}
}

TestJob

  3、配置Job执行方法

public sealed class ServerRunner : ServiceControl, ServiceSuspend
{
private readonly IScheduler scheduler; public ServerRunner()
{
scheduler = StdSchedulerFactory.GetDefaultScheduler();
} public bool Start(HostControl hostControl)
{
var jobList = new List<JobInfo>(); //配置JobList任务
jobList.AddRange(JobInfoList.JobList_ZhongShanHos); jobList.ForEach(
x =>
{
var dic = new Dictionary<string, JobInfo> { { "KEY", x } };
var map = new JobDataMap(dic);
var job =
JobBuilder.Create<TestJob>()
.WithIdentity(x.JobName, x.Group)
.UsingJobData(map)
.RequestRecovery()
.Build();
var trigger =
TriggerBuilder.Create()
.WithIdentity(x.JobName, x.Group)
.WithCronSchedule(x.Trigger)
.Build();
scheduler.ScheduleJob(job, trigger);
});
scheduler.Start();
return true;
} public bool Stop(HostControl hostControl)
{
scheduler.Shutdown(false);
return true;
} public bool Continue(HostControl hostControl)
{
scheduler.ResumeAll();
return true;
} public bool Pause(HostControl hostControl)
{
scheduler.PauseAll();
return true;
}
}

ServerRunner

  4、配置入口文件

class Program
{
static void Main(string[] args)
{
//配置Log4日志
log4net.Config.XmlConfigurator.Configure(); //Windows服务
HostFactory.Run(x =>
{
x.UseLog4Net(); x.Service<ServerRunner>(); x.SetDescription("Quartz日志记录服务");
x.SetDisplayName("Quartz");
x.SetServiceName("QuartzLog"); x.EnablePauseAndContinue();
});
}
}

Program

  至此,基本的所有配置就这样完成了,只要运行,就可以看到对应的服务的信息了。

  

  日志信息也记录在对应的(前面说设计的文档中)按照相面的代码选定的地址是根目录文件,如图所示:

windows服务

  制作windows服务,非常简单,只要调出cmd命令行,cd到指定文件的目录,输入应用程序名+install就可以,卸载的话就输入uninstall就可以了。如图所示:

源代码地址:GitHub

链接:https://github.com/JaminHuang/QuartzLog.git

Quartz任务调度 服务日志+log4net打印日志+制作windows服务的更多相关文章

  1. C# 制作Windows服务安装包

    C# 制作Windows服务安装包   这两天公司要用C#写一个windows服务,做成安装安装包.制作的过程中遇到了一些问题,写完之后总结一下.如果以后在用到的话可以可以参考一下,而且由于原来没有做 ...

  2. Apache添加到windows服务和移除Apache的windows服务

    Apache添加到windows服务和移除Apache的windows服务 Apache免安装版将其添加到Windows服务中: 打开cmd控制台,在上面输入"你的Apache安装目录\bi ...

  3. 制作Windows服务项目详细攻略

    1.在windows服务下面获得根目录: string assemblyFilePath = Assembly.GetExecutingAssembly().Location; string asse ...

  4. 制作Windows服务和安装程序(C#版)

    http://blog.sina.com.cn/s/blog_5f4ffa170100vt2b.html 1.创建服务项目: 打开VS 2005 编程环境,在C#中新建Windows服务程序 2.将安 ...

  5. Windows服务项目打包成安装包(Windows服务)-----------VS2017项目程序打包成.msi或者.exe

    VS2017项目程序打包成.msi或者.exe Windows服务项目使用VS2017项目程序打包成.msi或者.exe安装包 项目打包成安装包(Windows服务) 1.安装打包插件:Microso ...

  6. C# windows服务:如何检测指定的Windows服务是否启动

    public void CheckServerState(string ServiceName) { ServiceController[] service = ServiceController.G ...

  7. 使用C#创建windows服务续之使用Topshelf优化Windows服务

    前言: 之前写了一篇“使用C#创建windows服务”,https://www.cnblogs.com/huangwei1992/p/9693167.html,然后有博友给我推荐了一个开源框架Tops ...

  8. 如何制作windows服务安装包

    以下转自:http://blog.csdn.net/chainan1988/article/details/7087006 Window服务的安装有两个方式: 一.命令安装          通过命令 ...

  9. 制作windows服务

    1.下载winsw-1.8-bin.exe并更名: 2.配置winsw-1.8-bin.exe同上名<?xml version="1.0" encoding="UT ...

随机推荐

  1. Unity 移动键Q的三种用法 For Mac,Windows类同

    拖动整个场景:三指 (任何模式下)ALT+三指:旋转当前镜头 (任何模式下)双指前后滑动:缩放镜头 ps1:Q键移动的游戏场景,W移动的是游戏对象 ps2:三指 = 左键拖动

  2. Pyhton学习——Day61

    class Pagination(object): def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=7): ...

  3. Node Sass does not yet support your current environment: Windows 64-bit然如何解决,cnpm此问题解决方法

    这里直接说了node sass不支持当前环境,所以可以直接删掉原来不支持本机的node sass,再重新安装就行了 删除: npm uninstall --save node-sass 安装: npm ...

  4. FreeCodeCamp初级算法部分学习

    Reverse a String 翻转字符串 先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序,最后把数组转化成字符串. 你的结果必须得是一个字符串 当你完成不了挑战的时候,记得开大招 ...

  5. BZOJ 1016 最小生成树计数(矩阵树定理)

    我们把边从小到大排序,然后依次插入一种权值的边,然后把每一个联通块合并. 然后当一次插入的边不止一条时做矩阵树定理就行了.算出有多少种生成树就行了. 剩下的交给乘法原理. 实现一不小心就会让程序变得很 ...

  6. CF449D Jzzhu and Numbers (状压DP+容斥)

    题目大意: 给出一个长度为n的序列,构造出一个序列使得它们的位与和为0,求方案数 也就是从序列里面选出一个非空子集使这些数按位与起来为0. 看了好久才明白题解在干嘛,我们先要表示出两两组合位与和为0的 ...

  7. 为什么在index.jsp里面引入了common.js,在item-add.jsp以及其他一些jsp文件里面就不需要引入common.jsne ?

    那是因为,index.jsp页面的根节点是body,hrml.是一个完整的网页.那我们再看item-add.jsp页面,他节点是div,只是一个html的片段,并不是一个完整的网页,在easyUI中, ...

  8. 七、利用frp 穿透到内网的http/https网站,实现对外开放

    有域名的话使用域名,没有域名的话使用IP注意80端口是否被已经安装使用的nginx占用,若被占用,可以换成其他端口,比如8080,,或者利用nginx的反向代理实现frp服务端与nginx共用80端口 ...

  9. Django - 表与ORM操作

    Django - 表与ORM操作 一. 模板语言 模板中也有自己的语言, 该语言可以实现数据展示 - {{ 变量 }} - 循环 {% for i in all_publisher %} {{ for ...

  10. JAVA 多线程知识总结(一)

    一,线程的生命周期以及五种基本状态 关于JAVA线程的生命周期,首先看一下下面这张图 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌握了. Ja ...