Windows服务Demo

1创建一个Windows服务

2.添加安装程序

3.更改参数

Windows服务DemoWindows服务Demo

4.编写代码

5.打开bin,更改bat的路径

6.管理员模式运行bat文件

7.打开服务,找到刚刚发布的文件,如果发布失败,可以看bin里面的日志记录

8.开启服务,调试vs(附加到进程),找到刚刚的服务

9.调试成功,每次重新生成代码都需要关闭服务,再重亲开启才能调试

代码:

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.Configuration;
using KDMall.BLL;
using KDMall.Common;
using KDMall.Model;
using KDMall.ORM;
using Ninject;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using Dapper;
using System.Net.Mail;
using System.Collections;
using System.IO;
using System.Web;

namespace KDMall.Windows.RCCQService
{
    public partial class RccqService : ServiceBase
    {
        protected System.Timers.Timer timer = new System.Timers.Timer(1000 * 60);//1分钟一次检测
        public RccqService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            //每天固定时间(晚上1点)生成csv(一分钟检查一次)
            timer.Enabled = true;
            timer.Elapsed += Overtime_Elapsed;
        }

        void Overtime_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            SendTemplateMsg();
        }

        protected override void OnStop()
        {
        }


        #region 给会员发送模板消息

        /// <summary>
        /// 获取微信相关的api地址
        /// </summary>
        public string wechatApi = System.Configuration.ConfigurationManager.AppSettings["wechatApi"];

        public string appid = ConfigurationManager.AppSettings["KDMallAppId"];

        public StandardKernel ninjectKernel = null;

        private void SendTemplateMsg()
        {
            #region 发超时微信消息(消息模版)
            try
            {
                WriteLog();
                WriteLog();
                string template = ConfigurationManager.AppSettings["RccqTemplate"];
                #region 获取停车超时sql
                string sql = "select  u.real_name,u.open_id, r.id,r.car_no,r.parking_lot_no ,r.reserve_type,r.start_parkingtime,r.end_parkingtime,r.is_send,datediff(n,start_parkingtime,@now) as stopmin,datediff(n,end_parkingtime,@now) as diffmin " +
                    " from [dbo].[t_unloading_area_reserve]  r join kd_users..t_rccq_users  u on r.reserve_sc_name =u.user_name where (is_send =0 and reserve_type=2  and datediff(day,end_parkingtime, @now) = 0 and datediff(n,end_parkingtime, @now) >0 )" +
                    "order by id  desc  ";
                var reserveList = DapperHelper.GetList<reserveinfo>(DapperConnection.kd_mall, sql, new { now = DateTime.Now });
                WriteLog();
                WriteLog($"----- 停车已超时记录共{reserveList.Count}条 -----");
                WriteLog();
                #endregion
                #region 获取门卫信息sql
                string mwsql = "select * from t_rccq_users where type =3 and status=1";
                var mwlist = DapperHelper.GetList<GuardInfo>(DapperConnection.kd_user, mwsql, new { now = DateTime.Now });
                #endregion

                #region 获取停车还有5分钟超时sql
                string frontsql = "select  u.real_name,u.open_id, r.id,r.car_no,r.parking_lot_no ,r.reserve_type,r.start_parkingtime,r.end_parkingtime,r.is_send,datediff(n,start_parkingtime,@now)as stopmin,datediff(n,@now,end_parkingtime)as diffmin" +
                    " from [dbo].[t_unloading_area_reserve]  r join kd_users..t_rccq_users  u on r.reserve_sc_name =u.user_name where (is_frontsend =0 and reserve_type=2 and datediff(day,end_parkingtime, @now) = 0  and datediff(n,@now,end_parkingtime) between 0 and 5 )  " +
                    " order by id  desc  ";
                var frontList = DapperHelper.GetList<reserveinfo>(DapperConnection.kd_mall, frontsql, new { now = DateTime.Now });
                WriteLog();
                WriteLog($"----- 停车还有5分钟超时记录共{frontList.Count}条 -----");
                WriteLog();
                #endregion


                if (reserveList.Count > 0)
                {
                    foreach (var model in reserveList)
                    {
                        int status = 1; string msg = "";
                        var result = SendCouponTemplateMsg(model, template);
                        if (result.Item1 != 1)
                        {
                            status = 2; msg += "租户模板发送失败;";
                        }
                        foreach (var mvinfo in mwlist)
                        {
                            var mwresult = SendCouponTemplateMsgByMW(model, mvinfo, template);
                            if (mwresult.Item1 != 1)
                                status = 2; msg += "门卫(" + mvinfo.user_name + ")模板发送失败;";
                        }
                        if (status == 1)
                        {
                            DapperConnection.kd_mall.UpdateSql("update t_unloading_area_reserve set is_send=1 where id = @id", new { id = model.id });
                        }
                        else
                        {
                            DapperConnection.kd_mall.UpdateSql("update t_unloading_area_reserve set is_send=2,is_sendmsg = @sendmsg where id = @id", new { id = model.id, sendmsg = msg });
                        }

                    }
                }
                if (frontList.Count > 0)
                {
                    foreach (var model in frontList)
                    {
                        int status = 1;string msg = "";
                        var result = SendCouponTemplateMsgByfive(model, template);
                        if (result.Item1 != 1)
                        {
                            status = 2; msg += "租户模板发送失败;";
                        }
                        foreach (var mvinfo in mwlist)
                        {
                            var mwresult = SendCouponTemplateMsgByMWByfive(model, mvinfo, template);
                            if (mwresult.Item1 != 1)
                                status = 2; msg += "门卫("+mvinfo.user_name+")模板发送失败;";
                        }
                        if (status == 1)
                        {
                            DapperConnection.kd_mall.UpdateSql("update t_unloading_area_reserve set is_frontsend=1 where id = @id", new { id = model.id });
                        }
                        else
                        {
                            DapperConnection.kd_mall.UpdateSql("update t_unloading_area_reserve set is_frontsend=2 ,is_frontsendmsg =@sendmsg where id = @id", new { id = model.id, sendmsg = msg });
                        }
                    }
                }
                //记录日志
                WriteLog();
                WriteLog($"-----服务于 {DateTime.Now} 开始 -----");
                WriteLog();

                WriteLog();
                WriteLog();
            }
            catch (Exception ex)
            {
                WriteLog();
                WriteLog($"-----服务于 {DateTime.Now} 开始 发送异常:车位已超时,错误信息:{ex.Message.ToString()}-----");
                WriteLog();
            }
            #endregion


        }



        #region  停车超时发微信消息(消息模版)
        private Tuple<int, string> SendCouponTemplateMsg(reserveinfo model, string template)
        {
            try
            {
                var first = $"您好,您预定的车位(" + model.parking_lot_no + ")已超时,请您尽快离场,以免影响他人使用,感谢您的配合。";
                var data = getdata(model, first);
                var result = ValideOpenId(new ValideInfo() { template = template, open_id = model.open_id, data = data });
                return result;
            }
            catch (Exception ex)
            {
                return new Tuple<int, string>(1, ex.Message.ToString());
            }
        }

        private Tuple<int, string> SendCouponTemplateMsgByMW(reserveinfo model, GuardInfo mwinfo, string template)
        {
            try
            {
                var first = $"车牌号" + model.car_no + "在车位" + model.parking_lot_no + "已超时,请提醒车主马上离场,以免影响后续使用。";
                var data = getdata(model, first);
                var result = ValideOpenId(new ValideInfo() { template = template, open_id = mwinfo.open_id, data = data });
                return result;
            }
            catch (Exception ex)
            {
                return new Tuple<int, string>(1, ex.Message.ToString());
            }
        }

        private Tuple<int, string> SendCouponTemplateMsgByfive(reserveinfo model, string template)
        {
            try
            {
                WriteLog();
                WriteLog($"-----模板开始发送 -----");
                WriteLog();
                var first = $"您好,您预定的车位(" + model.parking_lot_no + ")还有5分钟超时,请您把握离场时间,以免影响他人使用,感谢您的配合。";
                var data = getdata(model, first);
                var result = ValideOpenId(new ValideInfo() { template = template, open_id = model.open_id, data = data });
                return result;
            }
            catch (Exception ex)
            {
                return new Tuple<int, string>(1, ex.Message.ToString());
            }
        }

        private Tuple<int, string> SendCouponTemplateMsgByMWByfive(reserveinfo model, GuardInfo mwinfo, string template)
        {
            try
            {
                var first = $"车牌号" + model.car_no + "在车位" + model.parking_lot_no + "还有5分钟超时,请提醒车主尽快离场,以免影响后续使用。";
                var data = getdata(model, first);
                var result = ValideOpenId(new ValideInfo() { template = template, open_id = mwinfo.open_id, data = data });
                return result;
            }
            catch (Exception ex)
            {
                return new Tuple<int, string>(1, ex.Message.ToString());
            }
        }


        //验证微信参数(open_id,app_id),发送模板
        public Tuple<int, string> ValideOpenId(ValideInfo model)
        {
            var template = model.template;
            var status = 2;
            var msg = "无法发送模板消息";
            var user_openid = model.open_id;//
            var accessToken = "";
            var access = KDHttpRequest.GetJsonByPost<JsonErrorResult<string>>($"{wechatApi}?mt=getAccessToken&appid={appid}");
            if (access != null && !string.IsNullOrEmpty(access.data) && access.result == 1)
                accessToken = DESEncrypt.Decrypt(access.data, "KDWechat");
            if (string.IsNullOrEmpty(user_openid) || string.IsNullOrEmpty(accessToken))
                return new Tuple<int, string>(status, $"获取{(string.IsNullOrEmpty(user_openid) == true ? "用户的openId" : "公众号的accessToken")}失败");
            if (template == null)
                return new Tuple<int, string>(status, "找不到对应的模板Id");
            var topColor = "#173177";
            var data = model.data;
            //记录日志
            WriteLog();
            WriteLog($"-----服务于 {DateTime.Now} 开始 ,发送内容:template_msg={Newtonsoft.Json.JsonConvert.SerializeObject(data)}-----");
            WriteLog();

            var template_id = template;
            var result = Senparc.Weixin.MP.AdvancedAPIs.TemplateApi.SendTemplateMessage(accessToken, user_openid, template, topColor, null, data);

            if (result != null && result.errcode == Senparc.Weixin.ReturnCode.请求成功)
            {
                status = 1;
                msg = "发送成功";
            }
            else
                msg = result.errmsg;
            return new Tuple<int, string>(status, msg);
        }

        //获取模板参数
        public object getdata(reserveinfo model, string first)
        {
            var remark = "";
            var keyword1 = "重庆来福士卸货区";
            var keyword2 = model.start_parkingtime;
            var keyword3 = model.stopmin + "分钟";
            var keyword4 = "";
            var color = "#173177";
            var data = new
            {
                first = new { value = first, color = color },
                keyword1 = new { value = keyword1, color = color },
                keyword2 = new { value = keyword2, color = color },
                keyword3 = new { value = keyword3, color = color },
                keyword4 = new { value = keyword4, color = color },
                remark = new { value = remark, color = color }
            };
            WriteLog();
            WriteLog($"----{JsonConvert.SerializeObject(data)}-- -----");
            WriteLog();
            return data;
            
        }



        public class JsonErrorResult<T>
        {
            /// <summary>
            /// 执行结果 1-成功,0-失败
            /// </summary>
            public int result { get; set; }
            /// <summary>
            /// 错误信息
            /// </summary>
            public string msg { get; set; }

            public T data { get; set; }
        }
        #endregion



        public class reserveinfo
        {
            public string real_name { get; set; }
            public int id { get; set; }
            public string open_id { get; set; }
            public string car_no { get; set; }
            public string parking_lot_no { get; set; }
            public string reserve_type { get; set; }
            public string start_parkingtime { get; set; }
            public string end_parkingtime { get; set; }
            public int is_send { get; set; }
            public int diffmin { get; set; }
            public int stopmin { get; set; }
            public string app_id { get; set; }
        }


        public class ValideInfo
        {
            public string open_id { get; set; }
            public string app_id { get; set; }
            public string template { get; set; }
            public object data { get; set; }
        }
        #endregion


        public void WriteLog(string log = "")
        {
            try
            {
                string log_address = ConfigurationManager.AppSettings["log_address"].ToString();
                log_address += DateTime.Now.ToString("yyyy-MM-dd HH") + ".log";
                System.IO.File.AppendAllText(log_address, log + "
");
            }
            catch (Exception ex)
            {
                string sql = "INSERT INTO [dbo].[t_wx_error_logs]([user_id],[login_name] ,[content],[add_time])  VALUES(0,'' ,'FtpCsvService定时服务更新出错,错误信息:" + ex.Message + "',getdate())";
                BLL.DapperHelper.ExecuteSql(DapperConnection.kd_log, sql, null);
            }
        }
    }
}