美文网首页
使用Topshelf+Quartz开发Windows定时任务

使用Topshelf+Quartz开发Windows定时任务

作者: Joshualley | 来源:发表于2021-03-12 15:27 被阅读0次

    使用Topshelf开发Windows服务,比起直接写Windows服务的优势在于,可以直接运行调试。开发完成后,直接使用install命令注册为服务即可,简单高效。

    一、准备工作

    1. 创建一个控制台应用


      image.png
    2. 在Nuget包管理器中搜索并安装Topshelf、Quartz、log4net这几个库


      image.png

    使用Topshelf框架

    1. 在程序入口类Program.cs中修改Main方法
    using Topshelf;
    
    namespace DemoService
    {
        class Program
        {
            static void Main(string[] args)
            {
                string serviceName = "DemoService";
                HostFactory.Run(config =>
                {
                    config.Service<StartService>(s =>
                    {
                        s.ConstructUsing(name => new StartService());
                        s.WhenStarted(service => service.Start());
                        s.WhenStopped(service => service.Stop());
                    });
    
                    config.RunAsLocalSystem();
                    config.SetDescription(serviceName);
                    config.SetServiceName(serviceName);
                    config.SetDisplayName(serviceName);
                });
            }
        }
    }
    
    1. 新增类文件:StartService.cs,并编写Start()、Stop()方法,这两个方法在Main方法中被注册为服务的启动和停止方法。
    namespace DemoService
    {
        public class StartService
        {
            public void Start()
            {
            }
            public void Stop()
            {
            }
        }
    }
    

    二、配置日志工具log4net

    1. 创建一个应用程序配置文件,改名为log4net.config

      image.png
    2. log4net.config<configuration>项中写入如下配置项

      <!-- Level的级别,由高到低 --> 
      <!-- None > Fatal > ERROR > WARN > DEBUG > INFO > ALL--> 
      <!-- 解释:如果level是ERROR,则在cs文件里面调用log4net的info()方法,则不会写入到日志文件中-->
      <log4net>
        <!--错误日志类-->
        <logger name="logerror"><!--日志类的名字-->
          <level value="ALL" /><!--定义记录的日志级别-->
          <appender-ref ref="ErrorAppender" /><!--记录到哪个介质中去-->
        </logger>
        <!--信息日志类-->
        <logger name="loginfo">
          <level value="ALL" />
          <appender-ref ref="InfoAppender" />
        </logger>
        <!--错误日志附加介质-->
        <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"><!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质-->
          <param name="File" value="Log\\LogError\\" /><!--日志输出到exe程序这个相对目录下-->
          <param name="AppendToFile" value="true" /><!--输出的日志不会覆盖以前的信息-->
          <param name="MaxSizeRollBackups" value="100" /><!--备份文件的个数-->
          <param name="MaxFileSize" value="10240" /><!--当个日志文件的最大大小-->
          <param name="StaticLogFileName" value="false" /><!--是否使用静态文件名-->
          <param name="DatePattern" value="&quot;Log_&quot;yyyyMMdd&quot;.htm&quot;" /><!--日志文件名-->
          <param name="RollingStyle" value="Date" /><!--文件创建的方式,这里是以Date方式创建-->
          <!--错误日志布局-->
          <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="&lt;HR COLOR=red&gt;%n异常时间:%d [%t] &lt;BR&gt;%n异常级别:%-5p &lt;BR&gt;%n异 常 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;"  />
          </layout>
        </appender>
        <!--信息日志附加介质-->
        <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
          <param name="File" value="Log\\LogInfo\\" />
          <param name="AppendToFile" value="true" />
          <param name="MaxFileSize" value="10240" />
          <param name="MaxSizeRollBackups" value="100" />
          <param name="StaticLogFileName" value="false" />
          <param name="DatePattern" value="&quot;Log_&quot;yyyyMMdd&quot;.htm&quot;" />
          <param name="RollingStyle" value="Date" />
          <!--信息日志布局-->
          <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="&lt;HR COLOR=blue&gt;%n日志时间:%d [%t] &lt;BR&gt;%n日志级别:%-5p &lt;BR&gt;%n日 志 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;"  />
          </layout>
        </appender>
      </log4net>
    
    1. 以上配置将会将Info日志保存至项目文件夹下的Log\\LogInfo\\,将错误日志保存至Log\\LogError\\,日志文件保存为.htm格式。

      转义字符对照表
      日志效果图
    2. Properties下的AssemblyInfo.cs中注册一下log4net.config配置文件

    [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", ConfigFileExtension = "config", Watch = true)]
    
    1. 编写LogHelper.cs
        public class LogHelper
        {
            //这里的 loginfo 和 log4net.config 里的名字要一样
            private static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo");
            //这里的 logerror 和 log4net.config 里的名字要一样
            private static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror");
            public static void Info(string message)
            {
                if (loginfo.IsInfoEnabled)
                {
                    loginfo.Info(message);
                }
            }
    
            public static void Error(string message, Exception ex)
            {
                if (logerror.IsErrorEnabled)
                {
                    logerror.Error(message, ex);
                }
            }
        }
    

    三、使用Quartz编写定时任务

    1. 创建一个DemoJob.cs
    using Quartz;
    using System;
    
    namespace DemoService.Jobs
    {
        public class DemoJob : IJob
        {
            public void Execute(IJobExecutionContext context)
            {
                Console.WriteLine("Hello");
                LogHelper.Info("Hello");
            }
        }
    }
    
    1. 使用Quartz框架,打开StartService.cs文件,在Start()方法中添加如下内容
        public class StartService
        {
            public void Start()
            {
                // 开启调度
                ISchedulerFactory sf = new StdSchedulerFactory();
                IScheduler scheduler = sf.GetScheduler();
                IJobDetail job = JobBuilder.Create<DemoJob>().Build();
                // 服务启动时执行一次
                // ITrigger triggerNow = TriggerBuilder.Create().StartNow().Build();
    
                // 每日22点执行一次
                ITrigger trigger = TriggerBuilder.Create()
                    .StartNow()
                    .WithCronSchedule("0 0 22 1/1 * ? ")
                    .Build();
                
                scheduler.ScheduleJob(job, trigger);
                scheduler.Start();
                LogHelper.Info("服务开始执行。");
            }
    
           public void Stop()
            {
    
            }
        }
    
    1. Cron表达式很强大,但刚上手需要一定的学习成本,此处附上一个生成表达式的工具:
      在线Cron表达式生成器传送门

    2. 想了解Cron 表达式,可参考该篇博文:https://www.cnblogs.com/yanghj010/p/10875151.html

    四、服务注册、卸载

    编写如下两个批处理文件,放在生成的目录下,需要注册、卸载时,直接执行即可。

    1. install.bat
    cd /d "%~dp0"
    生成的可执行文件名.exe install
    net start DemoService
    cmd
    
    1. uninstall.bat
    cd /d "%~dp0"
    生成的可执行文件名.exe uninstall
    cmd
    

    相关文章

      网友评论

          本文标题:使用Topshelf+Quartz开发Windows定时任务

          本文链接:https://www.haomeiwen.com/subject/fglzqltx.html