用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
buffalo的公告
<P><a target=blank href=http://wpa.qq.com/msgrd?V=1&Uin=760163&Site=blog of LJH&Menu=yes><img border="0" SRC=http://wpa.qq.com/pa?p=1:760163:1 alt="点击这里给我发消息"></a> </P> <script language="jscript"> var bsYear; var bsDate; var bsWeek; var arrLen=8; //数组长度 var sValue=0; //当年的秒数 var dayiy=0; //当年第几天 var miy=0; //月份的下标 var iyear=0; //年份标记 var dayim=0; //当月第几天 var spd=86400; //每天的秒数 var year1999="30;29;29;30;29;29;30;29;30;30;30;29"; //354 var year2000="30;30;29;29;30;29;29;30;29;30;30;29"; //354 var year2001="30;30;29;30;29;30;29;29;30;29;30;29;30"; //384 var year2002="30;30;29;30;29;30;29;29;30;29;30;29"; //354 var year2003="30;30;29;30;30;29;30;29;29;30;29;30"; //355 var year2004="29;30;29;30;30;29;30;29;30;29;30;29;30"; //384 var year2005="29;30;29;30;29;30;30;29;30;29;30;29"; //354 var year2006="30;29;30;29;30;30;29;29;30;30;29;29;30"; var month1999="正月;二月;三月;四月;五月;六月;七月;八月;九月;十月;十一月;十二月" var month2001="正月;二月;三月;四月;闰四月;五月;六月;七月;八月;九月;十月;十一月;十二月" var month2004="正月;二月;闰二月;三月;四月;五月;六月;七月;八月;九月;十月;十一月;十二月" var month2006="正月;二月;三月;四月;五月;六月;七月;闰七月;八月;九月;十月;十一月;十二月" var Dn="初一;初二;初三;初四;初五;初六;初七;初八;初九;初十;十一;十二;十三;十四;十五;十六;十七;十八;十九;二十;廿一;廿二;廿三;廿四;廿五;廿六;廿七;廿八;廿九;三十"; var Ys=new Array(arrLen); Ys[0]=919094400;Ys[1]=949680000;Ys[2]=980265600;Ys[3]=1013443200;Ys[4]=1044028800;Ys[5]=1074700800;Ys[6]=1107878400;Ys[7]=1138464000; var Yn=new Array(arrLen); //农历年的名称 Yn[0]="己卯年";Yn[1]="庚辰年";Yn[2]="辛巳年";Yn[3]="壬午年";Yn[4]="癸未年";Yn[5]="甲申年";Yn[6]="乙酉年";Yn[7]="丙戌年"; var D=new Date(); var yy=D.getYear(); var mm=D.getMonth()+1; var dd=D.getDate(); var ww=D.getDay(); if (ww==0) ww="星期日"; if (ww==1) ww="星期一"; if (ww==2) ww="星期二"; if (ww==3) ww="星期三"; if (ww==4) ww="星期四"; if (ww==5) ww="星期五"; if (ww==6) ww="星期六"; ww=ww; var ss=parseInt(D.getTime() / 1000); if (yy<100) yy="19"+yy; for (i=0;i<arrLen;i++) if (ss>=Ys[i]){ iyear=i; sValue=ss-Ys[i]; //当年的秒数 } dayiy=parseInt(sValue/spd)+1; //当年的天数 var dpm=year1999; if (iyear==1) dpm=year2000; if (iyear==2) dpm=year2001; if (iyear==3) dpm=year2002; if (iyear==4) dpm=year2003; if (iyear==5) dpm=year2004; if (iyear==6) dpm=year2005; if (iyear==7) dpm=year2006; dpm=dpm.split(";"); var Mn=month1999; if (iyear==2) Mn=month2001; if (iyear==5) Mn=month2004; if (iyear==7) Mn=month2006; Mn=Mn.split(";"); var Dn="初一;初二;初三;初四;初五;初六;初七;初八;初九;初十;十一;十二;十三;十四;十五;十六;十七;十八;十九;二十;廿一;廿二;廿三;廿四;廿五;廿六;廿七;廿八;廿九;三十"; Dn=Dn.split(";"); dayim=dayiy; var total=new Array(13); total[0]=parseInt(dpm[0]); for (i=1;i<dpm.length-1;i++) total[i]=parseInt(dpm[i])+total[i-1]; for (i=dpm.length-1;i>0;i--) if (dayim>total[i-1]){ dayim=dayim-total[i-1]; miy=i; } bsWeek=ww; bsDate=yy+"年"+mm+"月"; bsDate2=dd; bsYear="农历"+Yn[iyear]; bsYear2=Mn[miy]+Dn[dayim-1]; if (ss>=Ys[7]||ss<Ys[0]) bsYear=Yn[7]; document.write(bsDate+bsDate2+"日 "); document.write(bsWeek+" "); document.write(bsYear+" "+bsYear2); </script> <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type="text/javascript"> _uacct = "UA-547684-1"; urchinTracker(); </script>
文章分类
链接
51cmm
GotDotNet
LinuxByte
Linux下载
mp3下载
MSDN中文网站
ORACLE中国用户讨论组
PROXY(RSS)
中国系统分析员
数据库编程
存档

原创  用Delphi编写Win2000服务程序 收藏

一、Win2000服务简介

服务程序(Service Application)是一种运行于WinNT的后台程序,每个服务程序(Service Application)中可能包含若干个服务(Service),每个服务就是其中的一个线程(该服务也可以创建多个子线程)。采用服务,应用程序可以获得特殊的权限,而且不会被用户通过Win2000的任务管理器直接结束程序,所以服务常常用来实现一些特殊的目标。

通过Win2000控制面板中的服务管理工具,我们可以设置/查看服务的特性:

1)服务名称;(2)显示名称;(3)描述;(4)启动类型;(5)依赖关系;

其中,服务名称是标识给服务的。

Win2000C:\WINNT\System32\services.exe程序为例子,该Exe文件对应一个Service Application,是该服务程序的可见实体;该exe中包含多个服务(Service),例如AlerterDhcpDHCP Client),Messenger等。当我们结束一个服务的时候,该服务所在的Service Application中的其他服务并没有被终止。

?????? Delphi中,Borland的工程师为我们提供了TServiceApplicationTServiceTServiceThread等类,封装了大量细节,简化了服务程序的开发。

?

二、TServiceApplication

?????? Delphi中,类TServiceApplication就对应上述的ServiceApplication。利用Delphi的开发环境,我们新建一个Service Application Project,同时就创建了一个继承自TService的类。项目文件中的Application对象就是一个TServiceApplication实例。每个TServiceApplication包含若干个TService对象,正好对应上述的服务程序和服务之间的数量关系。

通过阅读TServiceApplicationTService类的定义,可以得知,TServiceApplicationTComponent类继承而来,TService从类TDataModule基础而来,Application对象负责各个TService对象的CreateDestroy。跟踪下列代码

Application.CreateForm(TService1, Service1);

可以发现创建的TService对象的Owner都是Application对象;在VCL FrameWorkOwner总是负责Destroy各个Component对象(VCLTComponent类采用了Composite模式),所以TServiceApplication也将Destroy各个TService对象。

下面跟踪TServiceApplication.Run的代码,可以发现TServiceApplication首先解析运行参数,实现了服务的InstallUninstall。然后,初始化一个ServiceStartTable数组,该数组包含了各个service对象的服务名称和运行入口;最后创建一个TServiceStartThread 对象,该对象是一个线程对象,从线程调用APIStartServiceCtrlDispatcher来启动ServiceStartTable中指定的若干个服务;而ServiceApplication主线程就不断循环,处理消息,比如接收请求来停止/暂停某个服务。

?

三、TService

TService类继承自类 TDataModule,这意味着我们可以加入大量的VCL控件,实现丰富的功能。此外,我们还可以处理OnStartOnPauseOnStopOnContinueOnCreateOnShutDown等事件。其中需要说明的是:OnStop表示该服务被停止;而OnShutDown表示该ServiceApplication停止运行,这意味着其他服务也被终止了;两者含义是不一样的。

前面讲过,ServiceApplication通过调用StartServiceCtrlDispatcher来启动各个服务。StartServiceCtrlDispatcher启动TService的入口,该入库就是TService.MainTService.Main首先注册该服务,然后调用TService.DoStartTService.DoStart创建一个内部TServiceThread成员对象,这是一个线程对象;考察TServiceThread.Execute可以得知,当我们处理的TService1. OnExecute,那么TService会把所有的请求委托给该TServiceThread成员对象处理,该对象以默认的方式处理所有的请求。

TService. ServiceExecuteTService的主体内容。一个服务要正常运行,除了需要处理它要关注的目标(比如监听某个端口、执行某个任务等)外,还要响应外部命令/请求:比如终止、暂停、恢复该服务。因此可以考虑创建一个专门的线程来完成该任务,而在ServiceExecute中处理外面命令/请求。因此代码如下:

?????? while not Terminated do begin

?????? ?????? ServiceThread.ProcessRequests(False);

?????? end;

当然,也可以在OnExecute中处理某些任务,如监听某个端口,但是这常常会导致该Service不能及时响应Stop/Pause等请求。当OnExecute执行完了,该服务实际上就完成了任务要结束了(terminate)。

?

参考资料:

MSDN,Delphi VCL源代码,Delphi帮助文档

发表于 @ 2004年08月11日 17:12:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:用.net中的socket实现文件传输 icknay [原作]  | 新一篇:天气预报

  • 发表评论
  • 评论内容:
  •  
Copyright © buffalo
Powered by CSDN Blog