引言

  现在许多的项目都需要定时的服务进行支撑,而我们经常用到的定时服务就是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、配置文件设置

  1. <configSections>
  2. <sectionGroup name="common">
  3. <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
  4. </sectionGroup>
  5. <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  6. </configSections>
  7.  
  8. <common>
  9. <logging>
  10. <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1211">
  11. <arg key="configType" value="INLINE" />
  12. </factoryAdapter>
  13. </logging>
  14. </common>
  15.  
  16. <log4net>
  17. <!--错误日志-->
  18. <!--自定义错误异常-->
  19. <appender name="CustomExAppender" type="log4net.Appender.RollingFileAppender">
  20. <param name="File" value="Log\\LogCustomEx\\" />
  21. <param name="AppendToFile" value="true" />
  22. <param name="MaxFileSize" value="" />
  23. <param name="MaxSizeRollBackups" value="" />
  24. <param name="StaticLogFileName" value="false" />
  25. <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
  26. <param name="RollingStyle" value="Date" />
  27. <layout type="log4net.Layout.PatternLayout">
  28. <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
  29. </layout>
  30. </appender>
  31.  
  32. <appender name="ErrorExAppender" type="log4net.Appender.RollingFileAppender">
  33. <param name="File" value="Log\\LogErrorEx\\" />
  34. <param name="AppendToFile" value="true" />
  35. <param name="MaxFileSize" value="" />
  36. <param name="MaxSizeRollBackups" value="" />
  37. <param name="StaticLogFileName" value="false" />
  38. <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
  39. <param name="RollingStyle" value="Date" />
  40. <layout type="log4net.Layout.PatternLayout">
  41. <conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别: %-5level %n日志描述:%message%newline %n" />
  42. </layout>
  43. </appender>
  44.  
  45. <!--CustomEx日志-->
  46. <logger name="LogCustomEx">
  47. <level value="INFO" />
  48. <appender-ref ref="CustomExAppender" />
  49. </logger>
  50. <!--Error日志-->
  51. <logger name="LogErrorEx">
  52. <level value="ERROR" />
  53. <appender-ref ref="ErrorExAppender" />
  54. </logger>
  55.  
  56. <!--服务执行日志-->
  57. <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
  58. <param name="File" value="Log\\ServerLog\\" />
  59. <param name="AppendToFile" value="true" />
  60. <param name="MaxFileSize" value="" />
  61. <param name="MaxSizeRollBackups" value="" />
  62. <param name="StaticLogFileName" value="false" />
  63. <param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
  64. <param name="RollingStyle" value="Date" />
  65. <layout type="log4net.Layout.PatternLayout">
  66. <param name="ConversionPattern" value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
  67. </layout>
  68. </appender>
  69.  
  70. <!-- 控制台前台显示日志 -->
  71. <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
  72. <mapping>
  73. <level value="ERROR" />
  74. <foreColor value="Red, HighIntensity" />
  75. </mapping>
  76. <mapping>
  77. <level value="Info" />
  78. <foreColor value="Green" />
  79. </mapping>
  80. <layout type="log4net.Layout.PatternLayout">
  81. <conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
  82. </layout>
  83. <filter type="log4net.Filter.LevelRangeFilter">
  84. <param name="LevelMin" value="Info" />
  85. <param name="LevelMax" value="Fatal" />
  86. </filter>
  87. </appender>
  88.  
  89. <root>
  90. <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) -->
  91. <level value="all" />
  92. <appender-ref ref="ColoredConsoleAppender"/>
  93. <appender-ref ref="RollingLogFileAppender"/>
  94. </root>
  95.  
  96. </log4net>

App.Config

让世界跑起来

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

  1. public class JobInfo
  2. {
  3. public JobInfo(string jobName, string group, string trigger, JobType jobType)
  4. {
  5. if (jobName == null || trigger == null || group == null)
  6. {
  7. throw new ArgumentNullException("jobName");
  8. }
  9. this.JobName = jobName;
  10. this.Trigger = trigger;
  11. this.Group = group;
  12. this.JobType = jobType;
  13. }
  14.  
  15. /// <summary>
  16. /// 名称
  17. /// </summary>
  18. public string JobName { get; set; }
  19.  
  20. /// <summary>
  21. /// Job的触发器 cron表达式
  22. /// </summary>
  23. public string Trigger { get; set; }
  24.  
  25. /// <summary>
  26. /// 群组
  27. /// </summary>
  28. public string Group { get; set; }
  29.  
  30. /// <summary>
  31. /// Job类型
  32. /// </summary>
  33. public JobType JobType { get; set; }
  34. }
  35.  
  36. /// <summary>
  37. /// Job类型枚举
  38. /// </summary>
  39. public enum JobType
  40. {
  41. /// <summary>
  42. /// 任务1
  43. /// </summary>
  44. Job1 = ,
  45. /// <summary>
  46. /// 任务2
  47. /// </summary>
  48. Job2 =
  49. }

JobInfo

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

JobInfoList

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

  1. public class TestJob : IJob
  2. {
  3. private static readonly log4net.ILog LogInfo = log4net.LogManager.GetLogger("LogCustomEx");
  4. private static readonly log4net.ILog LogError = log4net.LogManager.GetLogger("LogError");
  5.  
  6. public void Execute(IJobExecutionContext context)
  7. {
  8. var map = context.JobDetail.JobDataMap;
  9. var jobInfo = map["KEY"] as JobInfo;
  10. if (jobInfo == null) { return; }
  11.  
  12. //记录日志
  13. LogInfo.Info("\n【服务已启动】" + "\n【启动组】:" + jobInfo.Group + "\n【启动名称】:" + jobInfo.JobName + "\n【启动时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
  14.  
  15. try
  16. {
  17. switch (jobInfo.JobType)
  18. {
  19. //基础信息
  20. case JobType.Job1: LogInfo.Info("这是任务1"); break;
  21. case JobType.Job2: LogInfo.Info("这是任务2"); break;
  22.  
  23. default: break;
  24. }
  25. }
  26. catch (Exception ex)
  27. {
  28. //记录日志
  29. LogError.Error("\n【服务执行出错】" +
  30. "\n【启动组】:" + jobInfo.Group +
  31. "\n【启动名称】:" + jobInfo.JobName +
  32. "\n【时间】:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") +
  33. "\n【错误信息】:" + ex.Message);
  34. return;
  35. }
  36. }
  37. }

TestJob

  3、配置Job执行方法

  1. public sealed class ServerRunner : ServiceControl, ServiceSuspend
  2. {
  3. private readonly IScheduler scheduler;
  4.  
  5. public ServerRunner()
  6. {
  7. scheduler = StdSchedulerFactory.GetDefaultScheduler();
  8. }
  9.  
  10. public bool Start(HostControl hostControl)
  11. {
  12. var jobList = new List<JobInfo>();
  13.  
  14. //配置JobList任务
  15. jobList.AddRange(JobInfoList.JobList_ZhongShanHos);
  16.  
  17. jobList.ForEach(
  18. x =>
  19. {
  20. var dic = new Dictionary<string, JobInfo> { { "KEY", x } };
  21. var map = new JobDataMap(dic);
  22. var job =
  23. JobBuilder.Create<TestJob>()
  24. .WithIdentity(x.JobName, x.Group)
  25. .UsingJobData(map)
  26. .RequestRecovery()
  27. .Build();
  28. var trigger =
  29. TriggerBuilder.Create()
  30. .WithIdentity(x.JobName, x.Group)
  31. .WithCronSchedule(x.Trigger)
  32. .Build();
  33. scheduler.ScheduleJob(job, trigger);
  34. });
  35. scheduler.Start();
  36. return true;
  37. }
  38.  
  39. public bool Stop(HostControl hostControl)
  40. {
  41. scheduler.Shutdown(false);
  42. return true;
  43. }
  44.  
  45. public bool Continue(HostControl hostControl)
  46. {
  47. scheduler.ResumeAll();
  48. return true;
  49. }
  50.  
  51. public bool Pause(HostControl hostControl)
  52. {
  53. scheduler.PauseAll();
  54. return true;
  55. }
  56. }

ServerRunner

  4、配置入口文件

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. //配置Log4日志
  6. log4net.Config.XmlConfigurator.Configure();
  7.  
  8. //Windows服务
  9. HostFactory.Run(x =>
  10. {
  11. x.UseLog4Net();
  12.  
  13. x.Service<ServerRunner>();
  14.  
  15. x.SetDescription("Quartz日志记录服务");
  16. x.SetDisplayName("Quartz");
  17. x.SetServiceName("QuartzLog");
  18.  
  19. x.EnablePauseAndContinue();
  20. });
  21. }
  22. }

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. vue中slot的用法案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Linux网络配置、文件及命令

    Linux的网络配置是曾一直是我学习Linux的埋骨之地,投入了大量的精力和心神但是自己的虚拟机就是联不了网.原来一个大意,我一躺就是一年半.在这里简单的谈谈我对网络的微微认识. VMware的联网模 ...

  3. centos 7 防火墙配置

    centos 7里的防火墙使用的是firewall. 之前问过一个运维大牛,selinux的位置有点尴尬,说他们在工作中一般都会在第一时间关闭掉.我记得当时自己假设网站的时候就被这个坑了大半晚上.这个 ...

  4. SQL日期数据格式的处理

    sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007-0 ...

  5. vue2.0变化(转载)

    原文链接:https://www.cnblogs.com/itbainianmei/p/6062249.html 1.每个组件模板template,不再支持片段代码 之前: <template& ...

  6. [USACO07OPEN]Catch That Cow

    题目:洛谷P1588.HDU2717 题目大意:有一个人在点$n$,一头牛在点$k$,人每秒能从$x$移动到点$x+1$.$x-1$.$2x$,牛不会动,求最少多少秒后人能移动到牛所在的$k$. 思路 ...

  7. [poj 2976] Dropping tests (分数规划 二分)

    原题: 传送门 题意: 给出n个a和b,让选出n-k个使得(sigma a[i])/(sigma b[i])最大 直接用分数规划.. code: //By Menteur_Hxy #include & ...

  8. zabbix_get 获取agnet端mysql数据失败

    问题 在使用zabbix_get获取agent端的mysql数据时,总是报错,ERROR 2002 (HY000): Can't connect to local MySQL server throu ...

  9. [terry笔记]Python字符串

    如下学习python的字符串用法. print(dir(str)) ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', ...

  10. 编写html经常使用而又easy忘记的语句

    设置文件字符编码: <meta charset="utf-8"> 内部样式表: <style type="text/css"> hr { ...