Windows Service有着其特有的特性,在很多运用中可以发挥作用。比如长时间的,要求轮询的等。
Windows services enable you to perform tasks that execute as different background processes. You can use Windows services to perform tasks, such as monitoring the usage of a database. A Windows service executes in its own process space until a user stops it, or the computer is shut down.
在开发之前,理解几个概念和关键类:(权威解释见MSDN,这里是我的理解)
1. ServiceBase : 服务基础类。所有服务继承并实现其中的方法,即可以成为一个windows service.
You override the methods in the ServiceBase class to create a service application. The methods of this class enable you to specify the behavior of your service application.
Method
OnStart OnPause OnStop OnContinue OnShutDown OnCustomCommand OnPowerEvent(可以在电源状态发生变化时,比如电压降低等)
子类可以选择性的override其中的主要方法,比如OnStart,OnStop。基本上必须重写这个两个方法,这样你的类才有个性。
2. 服务安装和服务开发:
半天都用在了服务安装上。通过上面可以看出服务开发实际上并不是很难(我是说业务也很简单)。然后服务安装却显的很麻烦。
System.Configuration.Install.Installer类是安装的基础类。可以通过它来添加服务安装的其他Installer,比如LogInstaller,PerformanceCounterInstaller等。
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.eventLogInstaller1,
this.performanceCounterInstaller1,
this.serviceProcessInstaller1,
this.serviceInstaller1});
你可以通过这样的代码,也可以通过直接拖放这些组件实现。
ServiceInstaller必须制定servicename,这个名字不能和现有服务重复。
如果你添加了EventLogInstaller后,你必须小心了,它的Log和Source属性必须被制定。如Log=Application,Souce=ServiceInstall.ServiceName。
因为这个,我搞了很久:(
继续。。。。
你需要添加ServiceProcessInstaller,然而你需要注意它的Account属性。它默认为User,这会在安装服务时,弹出对话框信息,要求用户名和密码。如果没有指定正确,麻烦来了,并且你怎么也不会想到异常来自于这里。Exception信息是:
在“安装”阶段发生异常。
System.ArgumentOutOfRangeException: 索引和长度必须引用该字符串内的位置。
参数名: length
将它设置成LocalSystem就可以工作了.
3. ServiceController:
指定它的service名称后,就可以通过程序来控制你的服务。这个给无界面的服务带来了一些UI契机。
基本概念技术,进入开发,通过这个demo,实现一个简单的邮件发送功能。
1) 继承ServiceBase ,实现自己的服务。这个过程很简单,vs2005集成了开发Service的项。
partial class MailService : ServiceBase{。。}
默认要求override OnStart和OnStop两个方法。
protected override void OnStart(string[] args){} -----------这个参数还是很有意义的。比如这里邮件列表如果是文件,那么位置可以在这里指出。线程休眠时间也可以在这里给出。
如:
if (args.Length > 0)
{
try
{
SLEEP_TIME = Convert.ToInt32(args[0]);
}
catch (Exception)
{
Console.WriteLine("Error args !");
}
}
protected override void OnStop(){}
2) 安装服务。如果你的业务很简单,至此已经完成了一半工作。
服务安装,也可以通过vs2005中新添项完成。起码要添加两个Installer.一个是ServiceInstaller和ServiceProcessInstaller.
还可以添加EventLogInstaller和PerformanceCounterInstaller,MessageQueueInstaller
需要注意点上面已经提到了。
3) 这样基本完成了,安装你的服务,命令如下: InstallerUtil filename.exe
如果一切顺利。你就可以在SCM(Service Control Management)上看到你的服务了。
从上面的过程可以看出。windows service本身还是很简单的。所以有理由把更多的时间和精力用在你的业务上。这里是邮件发送,那么如何更好的,更方面的,更容易扩展的实现这个功能成了首要问题。
邮件配置:通过配置文件完成。
邮件发送:封装好的SMTP邮件发送类。
邮件列表:IGetMailList
业务:根据需求判断是否发送。
a. 配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<smtp deliveryMethod="Network" from="flyingchen@*****.com">
<network host="*****" port="25" defaultCredentials="true" userName="" password="" enableSsl="false"/>
</smtp>
<subject>
<content>Information</content>
</subject>
<body>
<content>
More info
</content>
</body>
</configuration>
在服务进程中依然可以通过配置改变。
b.这个自然不用多说。
c. 邮件列表来源很多。有文件形式的,有从数据库的,有从exchange server的,通过此接口可以屏蔽这些差异。返回给邮件发送类的就是IList<String>
d:public delegate bool NeedSend();定义这么一个委托。根据业务需求决定是否需要发送邮件。
至此结束。测试一下,小小“攻击”下,设置1秒发送一份到同事的邮箱。哈哈,撑爆他!