微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

定时器_使用C#开发windows服务定时发消息到钉钉群_群组简单消息

前言:本提醒服务,是由C#语言开发的,主要由windows服务项目和winform项目组成,运行服务可实现功能:向钉钉自定义机器人群组里,定时,定次,推送多个自定义消息内容,并实现主要功能的日志记录。  可以说功能强大!!!

 

备注: 本文主要2部分:1-关键代码,2-安装步骤。   

 

A-关键代码

1-服务:

 

public partial class MyTipsService : ServiceBase
    {
        public MyTipsService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            //服务启动
            List<TimeCycle> timeCycleList = new List<TimeCycle> {
                new TimeCycle {
                    ID=1,Action =this.SendTipsToDingding,BeginTime="09:05:00"09:15:002120
                },17:50:0018:05:003.MyProjectBugTips,1)">09:10:00服务启动);
            MyServiceHelp myServiceHelp =  MyServiceHelp(timeCycleList);
            myServiceHelp.Start();

        }

        void OnStop()
        {
            服务终止
            MyLog.WriteLog(服务终止);
        }


        /// <summary>
        /// 测试方法
        </summary>
         test()
        {
            MyProjectBugTips();
        }


        #region 获取提醒消息

         每天上下班提醒
        private  SendTipsToDingding()
        {
            MyLog.WatchAction(() =>
            {
                StringBuilder strBuilder =  StringBuilder();
                DateTime Now = DateTime.Now;
                if (Now.Hour < 12)
                {
                    strBuilder.Append(现在时间是:" + DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss") + \r\n);
                    strBuilder.Append(上班记得打卡!打卡迟到时间不能大于60分钟,多1分钟扣10块!\r\n上班记得佩戴胸牌!被抓住一次扣30块钱!\r\n);
                }
                else
                {
                    strBuilder.Append(下班记得打卡!\r\n);
                }


                string shangbanTipMessage = strBuilder.ToString();

                if (!.IsNullOrEmpty(shangbanTipMessage))
                {
                    DingDingHelp dingdingInstance = new DingDingHelp(ConfigHelper.GetAppSettingValue(dingdingGroupUrl));
                    string result = dingdingInstance.SendMesasge(shangbanTipMessage,"接收人手机号);

                    MyLog.WriteLog(发送打卡提醒消息结果:" + result);
                }
            });
        }

         我的项目BUG的提醒
         MyProjectBugTips()
        {
            MyLog.WatchAction(() =>
            {
                DateTime Now = DateTime.Now;

                List<string> bugWhereList = new List<string>(4);
                bugWhereList.Add(string.Format(@"{0}!='{1}'",Sys_commonlog._LOGTYPE_,1)">HttpException));
                bugWhereList.Add({0}>='{1}'Now.AddDays(-)));
                bugWhereList.Add({0}<='{1}'Now));


                A-获取所有人的异常监控配置
                NameValueCollection userNameValueColl = ConfigHelper.GetSectionNameValueCollection(bugUser);
                Dictionary<string,List<string>> userKeyWordListDic = new Dictionary<string>>(userNameValueColl.Count);
                List<string> userNameList = string>string> userPhoneList = (userNameValueColl.Count);

                List<string> allKeyWordWhereList = 0);
                string[] userArray = null;

                foreach (string userKeyAt in userNameValueColl)
                {
                    .IsNullOrEmpty(userKeyAt))
                    {
                        userArray = userKeyAt.Split('');
                        if (userArray.Length > )
                        {
                            string userName = userArray[];
                            userNameList.Add(userName);
                            userPhoneList.Add(userArray[]);

                            userKeyWordListDic.Add(userName,userNameValueColl[userKeyAt].Split().ToList());

                            if (userKeyWordListDic[userName].Count > )
                            {
                                string keyWord  userKeyWordListDic[userName])
                                {
                                    allKeyWordWhereList.Add({0} LIKE '%{1}%';


                string wheresql = {0} AND ({1})string.Join( AND  OR ;
                bugWhereList.Clear();
                bugWhereList = B-获取所有站点
                string[] websiteNameArray = ConfigHelper.GetAppSettingValue(websiteName").Split();


                C-收集每个人每个站的BUG汇总信息

                Dictionary<(websiteNameArray.Length);

                Sys_commonlogDAL instance =  Sys_commonlogDAL();
                string webSiteName  websiteNameArray)
                {
                    websiteDataListDic.Add(webSiteName,instance.Select(wheresql,Sys_commonlog._ID_ +  DESCConstr_ webSiteName)));
                }

                List<UserExectionHelp> userExectionHelpList = new List<UserExectionHelp>(userNameList.Count);
                List<Sys_commonlog> userWebsiteCommonLogList = ;
                List<WebSiteExectionHelp> webSiteExectionHelpList = ;
                WebSiteExectionHelp webSiteExection = ;
                int userBugTotalCount = ;
                List<string> userKeyWordList = for (var i = 0; i < userNameList.Count; i++)
                {
                    userKeyWordList = userKeyWordListDic[userNameList[i]];
                    webSiteExectionHelpList = new List<WebSiteExectionHelp>(websiteNameArray.Length);
                    var websiteDicItem  websiteDataListDic)
                    {
                        var userKeyWord  userKeyWordList)
                        {
                            userWebsiteCommonLogList = websiteDicItem.Value.FindAll(item => item.Url.Split(?')[].Contains(userKeyWord));
                            if (userWebsiteCommonLogList.Count > break;
                            }
                        }
                        if (userWebsiteCommonLogList != null && userWebsiteCommonLogList.Count > )
                        {
                            userBugTotalCount += userWebsiteCommonLogList.Count;
                            webSiteExection = new WebSiteExectionHelp { WebsiteName = websiteDicItem.Key,TotalCount = userWebsiteCommonLogList.Count,ExectionHelpList = userWebsiteCommonLogList };
                            webSiteExectionHelpList.Add(webSiteExection);
                        }
                    }

                    if (webSiteExectionHelpList.Count > )
                    {
                        userExectionHelpList.Add(new UserExectionHelp { UserName = userNameList[i],UserPhone = userPhoneList[i],TotalCount = userBugTotalCount,WebSiteExectionHelpList = webSiteExectionHelpList });
                    }

                    重置bug总数
                    userBugTotalCount = ;

                }

                D-循环输出信息
                DingDingHelp dingdingInstance = ));
                Sys_commonlog execItem = ;
                StringBuilder strBuilder =  StringBuilder();
                等待发送的消息数量
                int toBeSendMessageCount = ;
                userExectionHelpList.ForEach(item =>
                {
                    strBuilder.AppendFormat(网站异常_{0}_{1}_BUG总数:{2}:\r\nNow.ToShortDateString(),item.TotalCount);
                    MyLog.WriteLog(网站异常_{0}_{1}_BUG总数:{2}:
                    {
                        0; i < webItem.ExectionHelpList.Count; i++)
                        {
                            execItem = webItem.ExectionHelpList[i];
                            strBuilder.AppendFormat(【{0}-BUG-{1}】:\r\n));
                            strBuilder.AppendFormat(ID:{0}\nLogType:{1}\nCreateTime:{2}\nLogContent:{3}\nUrl:{4}\r\n;
                            超出50条自动发送
                            if (toBeSendMessageCount >= 50)
                            {
                                dingdingInstance.SendMesasge(strBuilder.ToString(),item.UserPhone);
                                toBeSendMessageCount = ;
                                strBuilder.Clear();
                            }
                        }
                    });
                    发送剩余未发送消息数量
                    if (toBeSendMessageCount > )
                    {
                        dingdingInstance.SendMesasge(strBuilder.ToString(),item.UserPhone);
                        strBuilder.Clear();
                    }
                    toBeSendMessageCount = ;
                });
                strBuilder = ;

                userNameList.Clear();
                userNameList = ;
                userPhoneList.Clear();
                userPhoneList = ;

                userExectionHelpList.Clear();
                userExectionHelpList = )
                {
                    userWebsiteCommonLogList.Clear();
                    userWebsiteCommonLogList = ;
                }
                websiteDataListDic.Clear();
                websiteDataListDic = if (webSiteExectionHelpList != )
                {
                    webSiteExectionHelpList.Clear();
                    webSiteExection = ;
                }
            });
        }

        #endregion

    }

 

原来服务帮助类中遇到了很多问题,如:如何统计多个任务中,每个任务的已执行次数问题?  如何让多个任务准时执行?   如何让多个任务中,每个任务按照自己的任务间隔执行?

针对这些问题,就设计了一个TimeCycel类(包含一个任务的ID,任务内容,任务的开始时间,任务时间间隔,任务已执行次数,任务最大执行次数)。

 

重点:服务运行后会形成一个单例模式,计时器,及服务帮助类的所有属性的初始化值,均会存在该单例中,因此我们可以将每个任务的信息记录在每个任务的实例中去,这样更合理;另外在任务执行时,新增了多线程的使用来处理任务的准时和执行次数问题。

原本走过一些弯路:原本TimeCycel类中没有任务已执行次数属性,我是通过一个方法计算的:当前时间-任务开始时间/任务执行间隔,计算的,但是这个方式计算存在时延问题以及任务的执行快慢,无法保证执行次数和执行间隔的准确性,使用每个任务的实例单独统计快捷方便,保证了已执行次数的准确性。

 

 MyServiceHelp
    {
        public MyServiceHelp(List<TimeCycle> timeCycleList)
        {
            this.TimeCycleList = timeCycleList;
            this.Timer =  Timer();
        }

         服务专属计时器
        private System.Timers.Timer Timer;

         认计时器时间间隔1秒(提高计时器开始时间准确度)
        double DefaultTimerInterval = 1 * 1000;

         设置多个循环周期
        public List<TimeCycle> TimeCycleList { get; set; }


         更新一个计时器的计时周期
        </summary>
        <param name="newTimerInterval">新的计时周期</param>
        <param name="isFirstStart">是否是首次更新计时器周期</param>
        void UpdateTimeInterval(double newTimerInterval,1)">bool isFirstStart = false)
        {
            if (this.Timer != null && newTimerInterval > )
            {
                .Timer.Stop();
                this.Timer.Interval != newTimerInterval)
                {
                    this.Timer.Interval = newTimerInterval;
                }
                if (isFirstStart)
                {
                    this.Timer.Elapsed += new System.Timers.ElapsedEventHandler(.ServiceAction);
                }
                this.Timer.AutoReset = true.Timer.Start();
            }
        }

         内部辅助方法
        <param name="sender"></param>
        <param name="e"></param>
        void ServiceAction(object sender,ElapsedEventArgs e)
        {
            List<TimeCycle> currentTimeCycleList = new List<TimeCycle>();

            DateTime Now = DateTime.Now;
            DateTime cycleBeginTime;
            DateTime cycleEndTime;
            foreach (TimeCycle timeCycle in .TimeCycleList)
            {
                cycleBeginTime = Convert.ToDateTime(timeCycle.BeginTime);
                cycleBeginTime = Now.Date.AddHours(cycleBeginTime.Hour).AddMinutes(cycleBeginTime.Minute).AddSeconds(cycleBeginTime.Second);
                cycleEndTime = Convert.ToDateTime(timeCycle.EndTime);
                cycleEndTime = Now.Date.AddHours(cycleEndTime.Hour).AddMinutes(cycleEndTime.Minute).AddSeconds(cycleEndTime.Second);
                if (cycleEndTime < cycleBeginTime)
                {
                    cycleEndTime = cycleEndTime.AddDays();
                }

                if (Now >= cycleBeginTime && Now <= cycleEndTime)
                {
                    if (timeCycle.ActionExecutionTimes < timeCycle.MaxActionTimes)
                    {
                        TimeSpan timeSpan = Now - cycleBeginTime;
                        bool isCanAction = (int)timeSpan.TotalSeconds % timeCycle.ActionSeconds == 0 ? true : ;
                         (isCanAction)
                        {
                            timeCycle.ActionExecutionTimes++;
                            currentTimeCycleList.Add(timeCycle);
                        }
                    }
                }
                
                {
                    不在计时周期内,已执行次数清零
                    timeCycle.ActionExecutionTimes = ;
                }
            }
            找到当前循环周期后,执行周期内动作
            if (currentTimeCycleList.Count > )
            {
                currentTimeCycleList.ForEach(item =>使用多线程执行任务,让代码快速执行
                    Task.Run(item.Action);
                });
            }
        }

         Start()
        {
            设置首次计时器周期(首次动作执行,是在计时器启动后在设置的时间间隔后做出的动作)
            this.UpdateTimeInterval(this.DefaultTimerInterval,1)">);

        }

    }

    <summary>
     计时周期类
    </summary>
     TimeCycle
    {
         唯一标识
        int ID { ; }
         开始时间(误差1秒=取决于计时器认时间间隔)
        string BeginTime {  结束时间
        string EndTime {  最大执行次数
        int MaxActionTimes {  计时周期内执行的动作(动作会在到达开始时间后的)
        public Action Action {  动作执行时间间隔(秒)
        int ActionSeconds {  方法执行次数
        internal int ActionExecutionTimes { ; }
    }

 

2-服务管理windowform代码

 

 Form1 : Form
    {
         Form1()
        {
            InitializeComponent();
            this.textServicePath.Text = ConfigHelper.GetAppSettingValue(serviceExeUrl);
        }

        static string serviceName = MyTips;


        void btnStartService_Click(.InstallService();
        }

        void btnEndService_Click(.UninstallService();
        }

        void btnTestService_Click( MyTipsService().test();
        }


        判断服务是否存在
        bool IsServiceExisted()
        {
            ServiceController[] services = ServiceController.GetServices();
            foreach (ServiceController sc  services)
            {
                if (sc.ServiceName.ToLower() == serviceName.ToLower())
                {
                    return ;
        }

        安装服务
         InstallService()
        {
            if (IsServiceExisted() == string[] args = new string[] { .textServicePath.Text };
                ManagedInstallerClass.InstallHelper(args);
                MessageBox.Show(安装成功!);

                using (ServiceController control =  ServiceController(serviceName))
                {
                    if (control.Status == ServiceControllerStatus.Stopped)
                    {
                        control.Start();
                    }
                }
            }
            
            {
                MessageBox.Show(已安装!);
            }
        }

        卸载服务
         UninstallService()
        {
             (IsServiceExisted())
            {
                停止服务
                 ServiceControllerStatus.Running)
                    {
                        control.Stop();
                    }
                }
                开始卸载
                string[] { /u卸载成功!);
            }
            已卸载!查找项目下、安装目录下服务EXE文件路径
        void btnFindExe_Click(string[] resultArray = Directory.GetFiles(Directory.GetCurrentDirectory(),1)">我的每日提醒项目.exeif (resultArray.Length > this.textServicePath.Text = resultArray[];
            }
        }
    }

 

B-安装过程:

准备资料:

1-钉钉群组添加自定义机器人,生成webhook链接URL。 

2-一个windows服务项目。

3-一个管理服务安装,卸载,启动,停止的winform窗体项目。

 

1-创建自定义机器人:

在钉钉的群组里,有群机器人的入口进入,添加一个自定义机器人:

 

添加成功后,会生成一个开发的webhook推送消息的接口地址:

 

 

 2-一个windows服务项目,以VS2015为例:

 

 

在服务的设计图里,右键添加安装程序:

 

 

 安装程序如下:我们可以设置关于服务的一些说明和程序设置:

 

 说明相关:描述,显示名,服务名称

服务程序账户设置:这里我们要选择本地系统

 

 至此一个服务的项目及安装程序就搭建起来了。

 

3-一个管理服务安装,卸载,启动,停止的winform窗体项目:

这里我只展示页面,具体创建很简单,就不多说了,我将安装和服务的启用,卸载和服务的停用写在一起了。

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐