文章来源:chrome://newtab/
所谓Windows后台服务,即后台自动运行的程序,一般随操作系统启动而启动,在我的电脑 服务后应用程序
服务里面能看到当前电脑的服务.一般而言,程序上用VC、C++写Windows服务,但是我对这些语言不是很熟,一般编程用C#较多,所以就用C#语言写了一个Windows服务.
其实需求是这样的,做那个报价系统的时候加入了发短信的功能,订单处理完即将发货的时候要发送短信都客户手机上,公司内部员工处理订单超时要自动发短信,群发产品促销信息到客户手机上等,还有定时发送短信的需求,所以最后面决定把发短信的模块独立出来,以后还有什么功能方便一起调用,而最终选择了采用Windows后台服务.
其实Windows服务并不好做到通用,它并不能在用户的界面显示一些什么信息等,它只是在后台默默的处理一些事情,起着辅助的作用.那如何实现发送段信通用调用的接口呢?它们之间的信息又是如何来交互呢?数据库!对,就是它存储数据信息的.而数据库都能很方便的访问操作.把发送短信的后台服务定时去访问一个数据库,而另外任何要发送短信的地方也访问数据库,并插入一条要发送的短信到表里面,稍后Windows后台服务访问该表将此短信发送出去.这可能是一个比较蠢的方法,但实现起来较简单.
首先,由于它是要安装的,所以它运行的时候就需要一个安装类Installer将服务安装到计算机,新建一个后台服务安装类继承自Installer,安装初始化的时候是以容器进行安装的,所以还要建立ServiceProcessInstaller和ServiceInstaller服务信息组件添加到容器安装,在Installer类增加如下代码:
private
System.ComponentModel.IContainer components = null;
private
System.ServiceProcess.ServiceProcessInstaller spInstaller;
private
System.ServiceProcess.ServiceInstaller sInstaller;
private void
InitializeComponent()
{
components = new
System.ComponentModel.Container();
//
创建ServiceProcessInstaller对象和ServiceInstaller对象
this.spInstaller = new
System.ServiceProcess.ServiceProcessInstaller();
this.sInstaller
=
new
System.ServiceProcess.ServiceInstaller();
//
设定ServiceProcessInstaller对象的帐号、用户名和密码等信息
this.spInstaller.Account =
System.ServiceProcess.ServiceAccount.LocalSystem;
this.spInstaller.Username = null;
this.spInstaller.Password = null;
// 设定服务名称
this.sInstaller.ServiceName = "SendMessage";
sInstaller.DisplayName = "发送短信服务";
sInstaller.Description = "一个定时发送短信的服务";
//
设定服务的启动方式
this.sInstaller.StartType =
System.ServiceProcess.ServiceStartMode.Automatic;
this.Installers.AddRange(new
System.Configuration.Install.Installer[] { this.spInstaller,
this.sInstaller });
}
再添加一个服务类继承自ServiceBase,我们可以重写基类的OnStart、OnPause、OnStop、OnContinue等方法来实现我们需要的功能并设置指定一些属性.由于是定事发送短信的服务,自然少不了Windows记时器,在OnStart事件里我们写入服务日志,并初始化记时器.
private
System.Timers.Timer time;
private static readonly string CurrentPath
=
Application.StartupPath + "\\";
protected
override
void
OnStart(string[] args)
{
string path
=
CurrentPath + "Log\\start-stop.log";
FileStream fs
=
new
FileStream(path, FileMode.Append, FileAccess.Write);
StreamWriter sw
=
new
StreamWriter(fs);
sw.WriteLine("The Service is
Starting On " +
DateTime.Now.ToString());
sw.Flush();
sw.Close();
fs.Close();
time
=
new
System.Timers.Timer(1000 * Convert.ToInt32(GetSettings("TimeSpan")));
time.Enabled
=
true;
time.Elapsed += this.TimeOut;
time.Start();
}
实例化记时器类启动后,将在指定时间间隔触发Elapsed指定事件,如上GetSettings为读取我App.config文件里一个配置节点(值为30)的方法,所以上面将会每隔30秒调用TimeOut方法.而改方法就是我们发短信的具体操作.代码如下:
private
void
TimeOut(object sender, EventArgs e)
{
try
{
if
(GetSettings("Enabled").ToLower() == "true")
{
SqlConnection con = new
SqlConnection(GetSettings("ConnString"));
SqlCommand
cmd =
new
SqlCommand("select
[sysid],[admin_inner_code],[user_inner_code],[phone],[message],[sendtime] from
[tbl_note_outbox]", con);
con.Open();
SqlDataReader rdr =
cmd.ExecuteReader();
while (rdr.Read())
{
string phone
=
rdr["phone"].ToString();
string message
=
rdr["message"].ToString();
string sendtime
=
rdr["sendtime"].ToString();
System.Text.Encoding encoder
=
System.Text.Encoding.GetEncoding("GB2312");
string url
=
string.Format("http://211.155.23.205/isapi.dll?SendSms&AgentID={0}&PassWord={1}&phone={2}&msg={3}&sendtime={4}",
GetSettings("AgentID"), GetSettings("PassWord"),
phone,System.Web.HttpUtility.UrlEncode( message,encoder),
sendtime);
System.Net.WebClient wClient = new
System.Net.WebClient();
string msg
=
System.Text.Encoding.Default.GetString(wClient.DownloadData(url));
wClient.Dispose();
//删除已经发送成功的,并保存发送记录
if (msg == "发送成功")
{
DateTime dtsend = sendtime
==
"0" ? DateTime.Now : DateTime.ParseExact(sendtime,
"yyyyMMddHHmmss", null);
string sql
=
string.Format("delete from [tbl_note_outbox] where [sysid]={0} INSERT
INTO [tbl_note_log]
([admin_inner_code],[user_inner_code],[status],[phone],[message],[sendtime])
VALUES('{1}','{2}','{3}','{4}','{5}','{6}')", rdr["sysid"], rdr["admin_inner_code"], rdr["user_inner_code"], msg, phone,
message, dtsend);
SqlConnection conn = new
SqlConnection(GetSettings("ConnString"));
SqlCommand
delete =
new
SqlCommand(sql,
conn);
conn.Open();
delete.ExecuteNonQuery();
conn.Close();
delete.Dispose();
}
}
rdr.Close();
con.Close();
cmd.Dispose();
}
}
catch (Exception
ex)
{
string errorPath = CurrentPath
+
"Log\\error.log";
if (!File.Exists(errorPath))
{
FileStream create
=
File.Create(errorPath);
create.Close();
}
FileStream fs = new
FileStream(errorPath, FileMode.Append, FileAccess.Write);
StreamWriter sw
=
new
StreamWriter(fs);
sw.WriteLine("Exception:
"
+ex.Message+" --"+
DateTime.Now.ToString());
sw.Flush();
sw.Close();
fs.Close();
}
}
上面我们使用try、catch访问数据库,并记录错误异常信息.
发送短信是使用发送一个Web请求发送出去的,要注意请求url字符串的编码类型,要与请求页面编码一致,不然会出现乱码.上面我们请求的是智网通集团短信(网址:http://www.09168.net/)的Web接口,通过访问他的网站来实现发短信,当然还要传递一些用户名、密码、手机号码和要发送的短信息等参数.他的收费平均大概为7分/条的样子,其实我原本不想用发送Web请求的这样方式来发送短信的,它本身提供了调用它发送短信的DLL,而且还有vc、delphi调用的Demo,但是没有用C#调用的例子,我刚开始试着用非托管动态链接库他提供的DLL,不知方法调用那里出错了一直都没能成功发送出短信,所以后来就用了他的Web方式接口了.他页面直接返回发送短信的状态信息.返回发送成功则短信发送成功,成功后我再将此条信息从要发送短信表里删除并保存在发送记录表里面,以备日后方便查询.其实登陆他的官网进入后台也能方便的查询,如下图
分享到:
相关推荐
本文将详细介绍如何使用 C# 语言开发一个 Windows 后台服务,用于定时访问数据库循环发送手机短信。该服务可以在后台自动运行,不需要用户干预,实现了自动发送短信的功能。 数据库访问 在该服务中,我们使用...
短信群发系统是一种基于C#编程语言开发的应用程序,它主要用于大批量地发送短信到多个手机接收者。C#,由微软公司推出,是.NET框架的主要编程语言,以其丰富的类库、面向对象的特性以及现代化的语法而广受欢迎。在这...
4. **定时器**:设置一个定时器来定期执行服务状态检查,防止因程序故障或其他原因导致的服务未被监控。 5. **日志记录**:为了追踪服务的运行情况和错误,实现日志记录功能,以便于后期分析和调试。 6. **持久化...
为了实时监控,可以将数据读取和存储操作封装到一个定时任务中,比如使用`System.Threading.Timer`类或`System.Timers.Timer`类,每隔一定时间执行一次。 7. 错误处理与日志记录: 在整个过程中,应捕获可能出现...
在IT行业中,C#是一种广泛使用的编程语言,尤其在开发Windows应用程序、Web应用程序以及游戏开发等领域。本资源涉及的是如何利用C#实现LED显示屏的信息显示功能。LED屏幕通常用于公共场所,如商场、车站等,用来展示...
在IT行业中,数据库连接管理是系统性能优化的关键环节,尤其是对于使用C#开发并依赖MySQL数据库的应用来说。本文将深入探讨“C#的MySQL数据库连接池源码,已稳定运行多年”的相关知识点。 首先,连接池是一种管理...
这段代码会创建一个无限循环,每天在指定的时间段内执行 `TimeTask`。`Thread.sleep()` 方法用于等待直到结束时间,这样可以避免立即调度下一个任务,而是等到第二天的同一时间段再执行。注意,每次任务执行完毕后,...
在C#中,可以使用Timer控件配合PictureBox来实现图片的定时切换,或者使用pictureBox的Image属性结合数组来实现图片的循环展示。`罗斌图片交替出现.txt`和`图片循环出现.txt`可能包含实现这一功能的代码示例或步骤...
在C#编程中,`DataGridView`控件是一个非常常用的数据展示工具,它允许开发者将数据库或其他数据源的数据以表格的形式展示在用户界面上。而自动翻页功能则为用户提供了一个更加便捷的方式来浏览大量数据,无需手动...
`MyRadioButton.cs`和`MyButton.cs`是自定义的单选按钮和按钮的逻辑代码,实现了特定的业务逻辑,例如用户通过单选按钮选择播放模式(定时、循环、随机等),按钮则执行播放控制操作。 `IPlayInfo.cs`可能是一个...
为了模拟作物生长的过程,需要在后台执行定时任务。C#中的`System.Threading`命名空间提供了丰富的多线程和异步操作支持,可以设置定时器定期检查作物生长状态。 4. **用户界面(UI)** QQ农场的UI需要展示农场布局...
例如,一个Repeater控件可以用来循环显示数据库中的图片,而一个Timer控件可以配合JavaScript实现定时更换幻灯片的效果。 最后,项目的改进和优化可以从多个角度考虑。例如,可以引入缓存机制,减少对数据库的频繁...
Timer的用法是指使用定时器控件来实现定时操作,定时器控件可以用来实现定时执行某个操作。 ado.net是C#编程语言中常用的数据库操作库,ado.net提供了对数据库的连接、查询、插入、删除、更新等基本操作。 下面是...
实例115 使用ServiceController组件控制计算机的服务 169 3.9 ImageList组件 171 实例116 使用ImageList组件制作动画图片 171 3.10 DirectoryEntry组件 172 实例117 使用DirectoryEntry组件建立虚拟目录 172 ...
7. Windows服务开发:C#支持创建后台运行的Windows服务,这在处理定时任务或需要持续运行的进程时非常有用。 8. 多线程编程:C#提供了System.Threading命名空间,用于实现并发和多线程操作。教程可能包含如何创建和...
- **实现方式**:可以通过编写SQL语句,每次只删除一部分记录,例如每次删除1000条记录,然后通过循环或定时任务的方式多次执行该操作。 2. **使用逻辑删除**: - **优点**:逻辑删除不会破坏原有的数据结构,也...
- **应用场景**:例如,可以用于定时备份数据库、实时监控数据库状态等场景。 ### 二、获取数据库表名和字段名 #### 知识点3:获取数据库表名 - **解释**:`GetTables`方法用于获取指定连接字符串下的所有表名。...
《C#小游戏开发详解》 在.NET框架下,C#是一种强大的编程语言,尤其适合用于开发桌面应用、游戏以及各种跨平台项目。本篇将详细探讨一个基于C#的小游戏的开发过程,揭示其中蕴含的.NET技术要点,帮助开发者深入理解...
在C#编程语言中,开发一个简单的门票销售系统是一个很好的学习实践项目,尤其对于初学者而言。这个项目可以帮助你理解基础的面向对象编程概念、数据库交互以及用户界面设计。下面我们将详细探讨C#门票销售系统的关键...
标题中的"C#桌面提醒工具、桌面闹钟"指的是一个用C#编程语言开发的应用程序,它的主要功能是在用户的计算机桌面上提供提醒服务,类似于一个桌面闹钟。这种工具可以帮助用户管理时间,设置重要的事件提醒,确保不会...