我们做项目过程中,一般都会有发送短信的需求。最常见的就是户注册或者登录时发送短信验证码。不同类型的短信发送,我们都可以放到到一张短信表中,然后通过一个定时的作业去执行短信发送。而定时作业的执行,我们就可以通过于Window服务去实现。(本篇只说window服务,具体实现短信发送的可以参考博客:http://www.cnblogs.com/ywl925/archive/2012/11/24/2786105.html

1、首先我们创建一张短信内容表:

  1. CREATE TABLE [dbo].[Message](
  2. [ID] [varchar](36) NOT NULL, --ID
  3. [MessageContent] [nvarchar](150) NOT NULL, --短信内容
  4. [Mobile] [varchar](11) NOT NULL, --手机号
  5. [SendType] [varchar](10) NOT NULL, --类型
  6. [SendNum] [int] NOT NULL, --发送次数
  7. [SendState] [int] NOT NULL, --发送状态
  8. [MsgError] [nvarchar](500) NULL, --错误日志
  9. [Enable] [bit] NOT NULL, --数据状态
  10. [ModifyDate] [datetime] NOT NULL, --修改时间
  11. [CreateDate] [datetime] NOT NULL, --创建时间
  12. CONSTRAINT [PK_Message] PRIMARY KEY CLUSTERED
  13. (
  14. [ID] ASC
  15. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  16. ) ON [PRIMARY]
  17.  
  18. GO

简单记录发送短信需要的一些基本信息。以后有需要发送的短信,直接添加到短信表中。

2、创建一个Window服务:

3、实现一个获取短信并发送的函数:

添加一个类SmsTran,类中只有一个方法Send。主要实现的功能是:

1)从数据库中获取n条发送状态为未发送并且发送次数小于最大发送次数的短信记录。

2)遍历获取到的集合,调用短信发送接口,并更新返回的结果状态(成功、失败或者其他)、发送次数修改时间

3)把更新后的数据集合同步到数据库。

  1. public class SmsTran
  2. {
  3. private static int MaxSendNum = ; //最多发送次数
  4. private static int MaxGetNum = ; //每次获取的最大条数
  5.  
  6. public static void Send()
  7. {
  8. using (var db = new DBContext())
  9. {
  10. var smsServer = new SendSMS(); //短信发送的帮助类
  11. var messages = db.Set<Message>().Where(s => s.SendState == && s.SendNum <= MaxSendNum).Take(MaxGetNum).ToList(); //获取未发送,并且发送次数小于最大发送次数的短信集合,每次取n条
  12. messages.ForEach(s =>
  13. {
  14. Logger.Debug(null, string.Format("短信发送:{0}, {1}", s.Mobile, s.MessageContent)); //记录日志
  15. var result = smsServer.Send(s.Mobile, s.MessageContent);
  16. if (Convert.ToInt32(result) > ) //根据发送结果更新短信记录
  17. {
  18. s.SendState = ;
  19. s.SendNum = s.SendNum + ;
  20. s.ModifyDate = DateTime.Now;
  21. }
  22. else
  23. {
  24. s.SendState = ;
  25. s.SendNum = s.SendNum + ;
  26. s.MsgError = result;
  27. s.ModifyDate = DateTime.Now;
  28. }
  29.   db.SaveChanges(); //同步短信信息到数据库
    });
  30. }
  31. }
  32. }

这里我采用的微软的EF读写数据。SendSMS类是自己写的一个发送短信帮助类,具体实现的方式可以参考我上面发的博客连接。Logger.Debug是一个简单记录日志的方法,有很多中方式可以实现,例如lognet4。

4、添加一个定时器执行短信发送:

在服务中添加命名空间System.Timer。在OnStart中添加一个定时器,定时器的执行事件就是上面我们添加的发送短信的方法。同时简单记录一下日志。

  1. public partial class Service : ServiceBase
  2. {
  3. private Timer timer;
  4.  
  5. private object obj = new object();
  6.  
  7. public Service()
  8. {
  9. InitializeComponent();
  10. }
  11.  
  12. protected override void OnStart(string[] args)
  13. {
  14. Logger.Debug(null, "短信服务已启动 " + DateTime.Now); //记录日志
  15. timer = new Timer();
  16. timer.Interval = ;
  17. timer.Elapsed += timer_Elapsed;
  18. timer.Enabled = true;
  19. }
  20.  
  21. void timer_Elapsed(object sender, ElapsedEventArgs e)
  22. {
  23. lock (obj)
  24. {
  25. try
  26. {
  27. SmsTran.Send();
  28. }
  29. catch (Exception ex)
  30. {
  31. Logger.Error(null, "短信服务发送错误!", ex); //记录日志
  32. }
  33. }
  34. }
  35.  
  36. protected override void OnStop()
  37. {
  38. timer.Enabled = false;
  39. Logger.Debug(null, "短信服务已停止 " + DateTime.Now); //记录日志
  40. }
  41. }

这里有一点需要注意,定时器Timer执行时间到时,如果你上一次的代码没有执行完,它会另起一个线程去执行。所以有可能我们上一次从数据库中取出来的短信还在发送中,没有更新发送状态到数据库,又被重新取出来重复次发送。所以这里我加了一个锁lock,执行完上一次的代码,才允许继续执行。

5、添加安装程序

在设计窗口中右键添加安装程序,会生成 serviceInstaller和serviceProcessInstaller两个组件。把serviceProcessInstaller的属性account改写为 LocalSystem。同时可以把serviceInstaller的属性ServiceName改写为你自己的服务程序名。

6、安装和卸载

编译后可以把生成的文件拷贝到你需要的地方,例如我在D盘中添加了一个文件夹SmsService用来放置刚才编译后的服务文件。然后在cmd中输入:

安装: C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe D:\SmsService\SmsService.exe

卸载: C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe -u D:\SmsService\SmsService.exe

大家可以把上面两个脚本命令保存成两个脚本文件Install.bat和Uninstall.bat添加服务文件夹下,以方便执行。安装后就可以在window服务中看到刚才我们自己添加的服务了。

因为我们在代码中添加了日志记录,所以启动服务后,就可以在文件夹下看到日志了。

随便把代码贴出来,有需要的参考一下:源码

C# 编写短信发送Window服务的更多相关文章

  1. 轻松集成腾讯云短信服务实现短信发送(Java实现)

    不论是阿里云还是腾讯云,要想在网站上实现短信发送功能,首先得保证你的网站域名是通过备案的,因为短信签名是需要用到备案过的域名截图,所以域名通过了,申请很快就会审批成功了. (说点题外话,备案的话,需要 ...

  2. c#简单易用的短信发送服务 悠逸企业短信服务

     悠逸企业短信发送服务,是一种比较简单易操作的短信发送服务,使用POST的方式,请求相应地址就可以实现短信发送功能 1 /// <summary> /// 短信发送服务 /// </ ...

  3. 4、下行短信发送WebService、下行短信发送服务 -功能详细设计 --短信平台

    3.  下行短信发送WebService 开发一个WebService,供第三方系统调用,用于发送短信.WebService接收数据后,将信息存储入数据库的短信发送数据表中. WebService参数 ...

  4. 阿里云短信发送服务SDK-Python3

    本文提供阿里云的短信发送服务SDK,使用Python3实现. # -*- coding: utf-8 -*- # pip install requests import requests import ...

  5. 043 用户注册功能03--Redis安装及完成短信发送功能

    1.Redis安装 (1)下载地址:https://github.com/MicrosoftArchive/redis/releases/tag/win-3.2.100   ( redis官网: ht ...

  6. ABP集成短信发送模块

    ABPZero并没有手机短信发送功能,现在我们来集成一个,为后面注册.登录作铺垫. 阿里云短信服务 首先需要在阿里云开通短信服务,连接地址 开通后,在签名管理中添加一个签名 在模板管理中添加一个模板, ...

  7. Java版阿里云通信短信发送API接口实例(新)

    阿里云通信(原名阿里大于)的短信服务(Short Message Service)是阿里云为用户提供的一种通信服务的能力,支持快速发送短信验证码.短信通知等. 完美支撑双11期间2亿用户,发送6亿短信 ...

  8. day102:MoFang:后端完成对短信验证码的校验&基于celery完成异步短信发送&flask_jwt_extended&用户登录的API接口

    目录 1.用户注册 1.后端完成对短信验证码的校验 2.基于celery实现短信异步发送 2.用户登录 1.jwt登录验证:flask_jwt_extended 2.服务端提供用户登录的API接口 1 ...

  9. PhpSms 稳定可靠的php短信发送库

    可能是目前最聪明.优雅的PHP短信发送库了.从此不再为各种原因造成的个别短信发送失败而烦忧! phpsms的任务均衡调度功能由toplan/task-balancer提供. GitHub地址:http ...

随机推荐

  1. daemon not running. starting it now on port 5037 ADB server didn't ACK

    adb kill-server adb start-server 显示如下 daemon not running. starting it now on port 5037 ADB server di ...

  2. [iOS基础控件 - 6.5] UITableView的数据刷新

    A.需求 1.以LOL英雄列表为蓝本,给其加上实时修改英雄名称的功能 2.使用UIAlertView 3.全局刷新reloadData 4.局部刷新     B.实现 1.使用UIAlertView ...

  3. [Xcode使用 - 2] 设置APP图标和启动画面

    1.App Icon   把所有图标文件拖放到 “Images.xcassets” 的”AppIcon” 里面     应对非视网膜和视网膜屏,APP有时会提供两套不同大小的图片,1倍图和2倍图,它们 ...

  4. maven依赖传递关系

    一.maven 依赖传递规则 举个例子,比如A依赖B,B依赖C,那么A也是依赖C的.A是对B的直接依赖,A对C是传递依赖 ①.最短路劲原则 如,路劲一:A依赖B,B依赖C,C依赖D(1.0.0): 路 ...

  5. 关于 mysql.test 数据库

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  6. 如何调整 php 应用的上传附件大小?

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  7. Myeclipse:No projects are available for deployment to this server!

    这是因为以前的项目不是用myEclipse创建的,所以用myeclipse deploy的时候找不到你的项目. 可以这样做:右击原项目名 - myeclipse - Add myeclipse  We ...

  8. com.opensymphony.xwork2.ActionSupport类源码

    version : xwork-2.1.0 /* * Copyright (c) 2002-2006 by OpenSymphony * All rights reserved. */ package ...

  9. 图像的稀疏表示——ScSPM和LLC的总结

    前言 上一篇提到了SPM.这篇博客打算把ScSPM和LLC一起总结了.ScSPM和LLC其实都是对SPM的改进.这些技术,都是对特征的描述.它们既没有创造出新的特征(都是提取SIFT,HOG, RGB ...

  10. 升级ADT22.6后,Android模拟器无法创建

    这 两天,在社区里看到有小伙伴们反应,自己在Eclipse下无法创建Android模拟器的问题.起初,自己也没太在意,我一直使用的是 Genymotion模拟器.然后,问题不解决,总有那么一天会让自己 ...