您的位置:首页 > 编程语言 > C#

C#实现Windows后台服务实例浅析

2010-07-07 11:34 543 查看
C#实现Windows后台服务实例之前要明白的一些概念:所谓Windows后台服务,即后台自动运行的程序,一般随操作系统启动而启动,在我的
电脑 服务后应用程序
服务里面能看到当前电脑的服务.一般而言,程序上用VC、C++写Windows服务,但是我对这些语言不是很熟,一般编程用C#较多,所以就用C#语言
写了一个Windows服务.

C#实现Windows后台服务实例其实需求是这样的,做那个报价系统的时候加入了发短信的功能,订单处理完即将发货的时候要发送短信都客户手机
上,公司内部员工处理订单超时要自动发短信,群发产品促销信息到客户手机上等,还有定时发送短信的需求,所以最后面决定把发短信的模块独立出来,以后还有
什么功能方便一起调用,而最终选择了采用Windows后台服务.

C#实现Windows后台服务实例其实Windows服务并不好做到通用,它并不能在用户的界面显示一些什么信息等,它只是在后台默默的处理一些
事情,起着辅助的作用.那如何实现发送段信通用调用的接口呢?它们之间的信息又是如何来交互呢?数据库!对,就是它存储数据信息的.而数据库都能很方便的
访问操作.把发送短信的后台服务定时去访问一个数据库,而另外任何要发送短信的地方也访问数据库,并插入一条要发送的短信到表里面,稍后Windows后
台服务访问该表将此短信发送出去.这可能是一个比较蠢的方法,但实现起来较简单.

C#实现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 });

}

C#实现Windows后台服务实例再添加一个服务类继承自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();

}

C#实现Windows后台服务实例实例化记时器类启动后,将在指定时间间隔触发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();

}

}

C#实现Windows后台服务实例上面我们使用try、catch访问数据库,并记录错误异常信息.
发送短信是使用发送一个Web请求发送出去的,要注意请求url字符串的编码类型,要与请求页面编码一致,不然会出现乱码.上面我们请求的是智网通集团短
信(网址:http://www.09168.net/)的Web接口,通过访问他的网站来实现发短信,当然还要传递一些用户名、密码、手机号码和要发送
的短信息等参数.他的收费平均大概为7分/条的样子,其实我原本不想用发送Web请求的这样方式来发送短信的,它本身提供了调用它发送短信的DLL,而且
还有vc、delphi调用的Demo,但是没有用C#调用的例子,我刚开始试着用非托管动态链接库他提供的DLL,不知方法调用那里出错了一直都没能成
功发送出短信,所以后来就用了他的Web方式接口了.他页面直接返回发送短信的状态信息.返回发送成功则短信发送成功,成功后我再将此条信息从要发送短信
表里删除并保存在发送记录表里面,以备日后方便查询.其实登陆他的官网进入后台也能方便的查询,如下图.



C#实现Windows后台服务实例发送短信服务的代码基本上搞定了,就看怎么在服务器上安装部署了.C#写的Windows后台服务不能直接安
装,需要借助.NET
Framework里面的InstallUtil.exe安装工具安装,我们可以做成一个执行CMD命令的文件BAT文件来安装启动它,命令如下:

%windir%/Microsoft.NET/

Framework/v2.0.50727/

InstallUtil.exe %CD%/

SendMessage.exe

net start SendMessage




安装完成以后,我们可以在我的电脑管理服务里面看到才安装上的后台服务.



经测试,采用定时访问数据库发送短信的服务并不是很耗资源,刚启动的时候只占用内存为7、8M左右,经过在服务器上连续运行几天不关闭占用的内存也
只升到15M左右,运行比较稳定
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: