C#:创建最简单的Windows服务以及实现定时任务(使用Quartz组件)

以下开发一个最简单的Windows服务,并设置定时任务,可以在指定时间自动执行业务。

先预览下Demo项目完成后的文件结构如下

1.创建windows服务项目

文件-》新建--》项目,选择"Windows服务",确定。

2.引用定时任务组件Quartz

右击项目-》管理NuGet程序包 查询quartz,安装对应版本。(当前默认是最新稳定版3.07需要.net4.52以上版本,不过我系统是4.5不支持,最后选择了2.62安装)

3.创建service

新建完项目会默认创建一个服务文件,本项目是WechatService.cs,双击该文件-》在设计页面右击-》选择“添加安装程序”。

点击serviceInstaller1,可以再属性页设置服务的相关参数,DisplayName是系统服务列表中显示的服务名,Description是服务描述。

设置完成后即可开始在服务文件WechatService.cs中编写服务执行的相关代码。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Quartz;
using Quartz.Impl;
using Quartz.Xml;
using Quartz.Simpl;
using log4net;
using Common;

namespace gszh.wx.winservice
{
    public partial class WechatService : ServiceBase
    {
/
        private static ILog log = LogManager.GetLogger(typeof(WechatService));
        private IScheduler scheduler;

        public WechatService()
        {
            InitializeComponent();
            //定时器Quartz
            try
            {
                scheduler = new StdSchedulerFactory().GetScheduler();
                XMLSchedulingDataProcessor process = new XMLSchedulingDataProcessor(new SimpleTypeLoadHelper());
                //读取定时任务配置xml文件
                Stream sr = new StreamReader(com.MapPath("/config/quartzJob.xml")).BaseStream;
                process.ProcessStream(sr, null);
                process.ScheduleJobs(scheduler);
                log.Debug("定时器启动.");
            }
            catch (Exception e)
            {
                log.Debug(e.ToString());
            }
        }

        protected override void OnStart(string[] args)
        {
            scheduler.Start();
            log.Debug("服务运行成功");
        }

        protected override void OnStop()
        {
            if (scheduler!=null)
            {
                scheduler.Shutdown(false);
            }
            log.Debug("服务运行停止");
        }
    }
}

代码中的quartzJob.xml是定时配置文件,后面会介绍配置。

4.配置定时任务文件参数

quartzJob.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>
    <!--Myjob Start-->
    <job>
      <name>Myjob</name>
      <group>JobGroup</group>
      <description>测试定时任务</description>
      <job-type>gszh.wx.winservice.Myjob,gszh.wx.winservice</job-type>
      <durable>true</durable>
      <recover>false</recover>
    </job>
    <trigger>
      <cron>
        <name>TestTrigger</name>
        <group>TriggerGroup</group>
        <job-name>Myjob</job-name>
        <job-group>JobGroup</job-group>
        <start-time>2019-10-10T08:00:00+18:00</start-time>
        <cron-expression>0 0/1 * * * ?</cron-expression>
      </cron>
    </trigger>
    <!--Myjob End-->
  </schedule>
</job-scheduling-data>

其中<job-type>gszh.wx.winservice.Myjob,gszh.wx.winservice</job-type>节点配置中,gszh.wx.winservice.Myjob是业务具体实现类的完全类名,gszh.wx.winservice是命名空间

<cron-expression>0 0/1 * * * ?</cron-expression>是crom表达式,此处代表每分钟执行一次

5.业务具体实现类

新建一个类gszh.wx.winservice.Myjob,此类要实现Quartz.IJob的接口Execute,在这个接口里编写具体业务功能。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Quartz;
using log4net;
using Common;

namespace gszh.wx.winservice
{
    [PersistJobDataAfterExecution]//保存执行状态
    [DisallowConcurrentExecution]//不允许并发执行
    public class Myjob : IJob
    {
        private static ILog log = LogManager.GetLogger("Myjob");
        public void Execute(IJobExecutionContext context)
        {
            log.Debug("任务执行..");
        }
    }
}

至此,一个最简单的windows服务已经创建完成,接下来就是要安装到系统中。

6.部署服务

开发完的服务程序,需要安装到系统中才能运行,微软提供了工具,

详见https://docs.microsoft.com/zh-cn/dotnet/framework/windows-services/how-to-install-and-uninstall-services?redirectedfrom=MSDN

但本Demo使用一个很简易的Winform程序来执行安装服务的功能。

winform的界面和代码如下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.ServiceProcess;
using System.Configuration.Install;
using log4net;

namespace WechatServiceClient
{
    public partial class frmMain : Form
    {
        string serviceName ;
        string serviceFilePath ;
        private static ILog log = LogManager.GetLogger(typeof(frmMain));
        public frmMain()
        {
            InitializeComponent();
            serviceName = "WechatGszhService";
            //服务程序所在位置
            serviceFilePath = Application.StartupPath + "\\gszh.wx.winservice.exe";
        }

        
        private void btnInstall_Click(object sender, EventArgs e)
        {
            string msg = "";
            try
            {
                if (this.IsServiceExisted(serviceName))
                {
                    msg = "该服务已经存在,请先卸载后再安装.";
                    log.Debug(msg);
                    MessageBox.Show(msg, "提示", MessageBoxButtons.OK);
                }
                else
                {
                    this.InstallService(serviceFilePath);
                    msg = "服务安装完成.";
                    log.Debug(msg);
                    MessageBox.Show(msg, "提示", MessageBoxButtons.OK);
                } 
            }
            catch (Exception ex)
            {
                log.Debug(ex.ToString());
            }
        }

        private void btnUninstall_Click(object sender, EventArgs e)
        {
            if (this.IsServiceExisted(serviceName))
            {
                this.ServiceStop(serviceName);
                this.UninstallService(serviceFilePath);
                string msg = "服务卸载完成.";
                log.Debug(msg);
                MessageBox.Show(msg, "提示", MessageBoxButtons.OK);
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (this.IsServiceExisted(serviceName))
                this.ServiceStart(serviceName);
            string msg = "服务启动完成.";
            log.Debug(msg);
            MessageBox.Show(msg, "提示", MessageBoxButtons.OK);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (this.IsServiceExisted(serviceName)) this.ServiceStop(serviceName);
            string msg = "服务已暂停.";
            log.Debug(msg);
            MessageBox.Show(msg, "提示", MessageBoxButtons.OK);
        }
        //判断服务是否存在
        private bool IsServiceExisted(string serviceName)
        {
            ServiceController[] services = ServiceController.GetServices();
            foreach (ServiceController sc in services)
            {
                if (sc.ServiceName.ToLower() == serviceName.ToLower())
                {
                    return true;
                }
            }
            return false;
        }

        //安装服务
        private void InstallService(string serviceFilePath)
        {
            using (AssemblyInstaller installer = new AssemblyInstaller())
            {
                installer.UseNewContext = true;
                installer.Path = serviceFilePath;
                IDictionary savedState = new Hashtable();
                installer.Install(savedState);
                installer.Commit(savedState);
            }
        }

        //卸载服务
        private void UninstallService(string serviceFilePath)
        {
            using (AssemblyInstaller installer = new AssemblyInstaller())
            {
                installer.UseNewContext = true;
                installer.Path = serviceFilePath;
                installer.Uninstall(null);
            }
        }
        //启动服务
        private void ServiceStart(string serviceName)
        {
            using (ServiceController control = new ServiceController(serviceName))
            {
                if (control.Status == ServiceControllerStatus.Stopped)
                {
                    control.Start();
                }
            }
        }

        //停止服务
        private void ServiceStop(string serviceName)
        {
            using (ServiceController control = new ServiceController(serviceName))
            {
                if (control.Status == ServiceControllerStatus.Running)
                {
                    control.Stop();
                }
            }
        }
    }
}

7.运行服务

winform程序编译后,将生成的exe文件复制到服务程序所在目录运行。即可对服务进行安装、卸载、启动、暂停等操作。

 8.调试服务

先运行服务,然后在VS的菜单“调试”-》“附加到进程”,选中你的应用服务进程名后确定附加。接下来就可以按平常的调试步骤,设定好断点,运行调试功能。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值