1创建一个Windows服务
2.添加安装程序
3.更改参数
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); } } } }