陈剑辉
摘要 本文首先描述了Windows服务程序的优点,然后通过具体编写Windows服务程序,实现了在特定环境下对文件的自动删除。 关键词 Windows服务,程序,自动删除 一、引言 2006年初,江阴电视台引进了南京格非公司“Aces数字硬盘录像系统”,该系统可以全天候、实时地把江阴电视台四个频道每天播出的电视节目以录像方式完全克隆到计算机硬盘上,并且以文件格式保存下来。 由于该系统源源不断地把江阴电视台四个频道的播出节目内容写在计算机硬盘上,而计算机硬盘的容量毕竟有限,并且保存在硬盘上的播出数据具有一定的时效性,也就是说这些数据只保留一定时间(比如说两个月),不需要永久地保留。这样一来,就需要人工定期、不定期地根据剩余硬盘空间的大小,以播出时间为顺序,把一些保存在硬盘上以前的电视节目数据从硬盘上删除。以便腾出硬盘空间,存放即将播出的电视节目内容,否则,如果硬盘写满了,就没有空间存放正在播出(即将播出)的电视节目内容。经过一段时间的摸索,笔者在Visual Studio.NET环境下,利用Visual Basic.NET编程,实现了完全由计算机自己定期完成上述任务,而且这个程序只要计算机开机,就始终处于运行状态。 二、编写Windows服务程序的应用实践 下面向大家具体介绍利用VB.NET编写Windows服务应用程序。 首先,向大家简要介绍 “Aces数字硬盘录像系统”。“Aces数字硬盘录像系统”采用的是SATA结构,外挂四个小硬盘,它们分别是F盘,G盘,H盘,J盘。又把这四个小硬盘分为两组,其中F盘和H盘为一组,用于存放“新闻综合”频道和“城市”频道的节目,G盘和J盘为一组,用于存放“电视剧”频道和“电影”频道节目。“Aces数字硬盘录像系统”先把“新闻综合”频道和“城市”频道的节目内容按时间顺序,以每天一个文件夹的形式先写到F盘上,等到F盘写满后,“Aces数字硬盘录像系统”把接下来的上述两个频道的节目再往H盘上写,这样,当H盘快要写满的时候,就需要我们人工删除一些以前存放在F盘上的节目内容,腾出硬盘空间(以备当H盘写满后,用来存放这两个频道即将播出的节目内容)。这样,等到H盘写满后,“Aces数字硬盘录像系统”又自动把上述两个频道的节目内容往H盘上写,等到H盘快要写满的时候,又需要我们人工删除掉存放在F盘上以前的节目内容,以便腾出硬盘空间,存放上述两个频道即将播出的节目内容。 就这样,按照“写F盘----写H盘----人工删除F盘----再写F盘----再人工删除H盘----再写H盘”的规律,循环往复。这样,“新闻综合”频道和“城市”频道的节目内容被保存在F和H盘上。 对于G盘和J盘同样如此,只不过他们存放的是“电视剧”频道和“电影频道的节目内容”。 不难发现,F、H盘上节目内容的删除和G、J盘上节目内容的删除,这两个操作是相互独立的,为此,在编程时把它们作为独立的过程分别来处理。 下边谈谈通过编程对“Aces数字硬盘录像系统”功能的改进: 通过观察,电视台每个频道每天的节目(包括节目结束后INFOTV的内容)大概需要8G的空间来保存,而F,G,H,J每个盘空间为400G,按此推算,要写满它们,大概需要两个月时间,就需要人工删除一些节目内容,也就是说,电视节目内容最多可以保存两个月的时间。 经过反复推算,当F、G、H、J的剩余空间为50G时,开始执行“删除”操作比较合理。因为这样可使电视节目内容保存地时间更长一些。 再简述编程思路:把Widows服务程序称为:DiskSpaceManagementService。为了方便处理,首先在定义一个数据结构,用以定义各个盘符以及它们的剩余空间的最小值(这里,定义为50G)。同时定义了几个函数DiskSpaceManagement(),DiskSpace(),GetEarlestFolder()。其中DiskSpace()用以获得某一逻辑盘的剩余空间,GetEarlestFolder()用以获得逻辑盘上的创建日期最早的一个目录。DiskSpaceManagement用以检查逻辑盘上剩余空间是否已经小于规定的空间,如果小于,则进行删除操作。 在OnStart()函数中定义相应的四个盘符和它们的最小允许剩余空间、启动了一个周期为1小时的定时器、并调用DiskSpaceManagement()进行检查。而在定时器的Elapsed()事件中通过比较上一时刻与下一时刻的日期是否相同,确定是否跨越了一天,如果跨越了一天,则调用DiskSpaceManagement()进行检查,从而实现了每天检测一次的需求,就是说,在每天零点左右程序都要检查一次F和H盘(G和J)的剩余空间,如果F和H盘(G和J盘)的剩余空间都小于50G时,程序便自动删除F和H盘(G和J盘)上最早的一天的节目内容;如果F和H盘(G和J盘)的剩余空间都大于50G时,则程序什么也不做,然后等新的一天来临时,程序则又重复上述操作。这样,就实现了节目内容的自动删除。 程序实现的核心代码如下: Public Class DiskSpaceManagementService Inherits System.ServiceProcess.ServiceBase Private WithEvents controltimer As Timer Dim tempDate As Date
Structure DriverInformation Dim strDriverName As String Dim intMinVol As Integer
End Structure
Dim Driver(4) As DriverInformation #Region " 组件设计器生成的代码 " Public Sub New() MyBase.New() InitializeComponent() ' 在 InitializeComponent() 调用之后添加任何初始化 End Sub
'UserService 重写 dispose 以清理组件列表。 Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub
' 进程的主入口点 <MTAThread()> _ Shared Sub Main() Dim ServicesToRun() As System.ServiceProcess.ServiceBaseServicesToRun = New System.ServiceProcess.ServiceBase() {New DiskSpaceManagementService} System.ServiceProcess.ServiceBase.Run(ServicesToRun) End Sub
Private components As System.ComponentModel.IContainer <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() 'DiskSpaceManagementService Me.CanShutdown = True Me.ServiceName = "DiskSpaceManagementService" End Sub #End Region
Protected Overrides Sub OnStart(ByVal args() As String) tempDate = Now controltimer = New Timer controltimer.Interval = 3600000 controltimer.AutoReset = True controltimer.Start() '此处设置需要整理的盘符和最小剩余空间(以M为单位) Driver(0).strDriverName = "F" Driver(0).intMinVol = 50000 Driver(1).strDriverName = "H" Driver(1).intMinVol = 50000 Driver(2).strDriverName = "G" Driver(2).intMinVol = 50000 Driver(3).strDriverName = "J" Driver(3).intMinVol = 50000
'一启动就先整理一下 DiskSpaceManagement(Driver(0), Driver(1)) DiskSpaceManagement(Driver(2), Driver(3)) End Sub
Protected Overrides Sub OnStop() ' 在此处添加代码以执行停止服务所需的关闭操作。 controltimer.Close() End Sub
Public Sub DiskSpaceManagement(ByVal driverA As DriverInformation, ByVal driverB As DriverInformation) Dim Fld1 As Scripting.Folder Dim Fld2 As Scripting.Folder Dim Fld3 As Scripting.Folder Dim Fld4 As Scripting.Folder On Error GoTo ErrorInfor If (DiskSpace(driverA.strDriverName) < driverA.intMinVol) And (DiskSpace(driverB.strDriverName) < driverB.intMinVol) Then Fld1 = GetEarlestFolder(driverA) Fld2 = GetEarlestFolder(driverB) '如果没有取出最早目录,则什么都不做 If Fld1 Is Nothing Then Return If Fld2 Is Nothing Then Return If Fld1.DateCreated < Fld2.DateCreated Then '记录进日志 EventLog.WriteEntry(ServiceName & " - Delete", "Delete Folder " & Fld1.Name) Fld1.Delete(True) Else '记录进日志 EventLog.WriteEntry(ServiceName & " - Delete", "Delete Folder " & Fld2.Name) Fld2.Delete(True) End If End If Return ErrorInfor: EventLog.WriteEntry(ServiceName & "-" & Err.Description) End Sub
'获得磁盘分区的剩余空间的函数,以M为单位 Public Function DiskSpace(ByVal DrivePath As String) As Double Dim Fso As New FileSystemObject Dim drvDisk As Drive, strResult As String drvDisk = Fso.GetDrive(Left(Trim(DrivePath), 1) & ":\") DiskSpace = drvDisk.FreeSpace / 1024 ^ 2 End Function
'获得一个磁盘分区的包含的文件夹中创建日期最早的一个文件夹 Public Function GetEarlestFolder(ByVal Driver As DriverInformation) As Folder Dim Flds As Folders Dim Fld As Folder Dim Fld1 As Folder Dim tempFld As Folder Dim Date1 As Date Dim Fso As New FileSystemObject '取最早日期目录夹 Flds = Fso.GetFolder(Left(Trim(Driver.strDriverName), 1) & ":\").SubFolders() Date1 = Now If Flds.Count > 0 Then For Each Fld In Flds If Fld.DateCreated() < Date1 Then Date1 = Fld.DateCreated tempFld = Fld End If Next Fld1 = tempFld Else Fld1 = Nothing End If Return Fld1 End Function
Private Sub controltimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles controltimer.Elapsed '如果日期变了,意味着跨越12PM时,进行整理 If Now.Day > tempDate.Day Then EventLog.WriteEntry(ServiceName, "Disk check began...") DiskSpaceManagement(Driver(0), Driver(1)) DiskSpaceManagement(Driver(2), Driver(3)) EventLog.WriteEntry(ServiceName, "Disk check finished...") End If tempDate = Now End Sub
Protected Overrides Sub OnPause() controltimer.Close() End Sub
Protected Overrides Sub OnContinue() controltimer.Interval = 3600000 controltimer.AutoReset = True controltimer.Start() End Sub End Class
最后,通过Windows服务安装工具Srvinstw使DiskSpaceManagementService成为Windows服务程序。
该服务程序启动后,就在后台始终处于运行状态,结果如图1所示。

图 1 服务程序启动 然后,再通过计算机“事件服务查看器”,就能看到该服务程序的运行结果。下面通过“事件服务查看器”来详细介绍其某一天的运行结果,如图2所示。

图2 日志查看 正如在图2中所看到的,当2006年9月26日这天来临时,该服务程序共进行三项操作,然后,按照时间发生的顺序,分别将它们称为:A、B、C。然后,通过鼠标分别“双击”它们,就能进一步看到它们的具体操作: 通过鼠标“双击”A项,这时,看到的结果如图3所示:在2006年9月26日零时零分(即9月26日这一天来临时),该服务程序开始检查F盘和H盘的剩余空间。

图3 显示属性
通过鼠标双击“B”项,这时,看到的结果如图4所示。在2006年9月26日零点零分30秒时,由于该服务程序检测到F和H盘的剩余空间都小于50G,此时,便把保存在F和H盘上最早这一天(2006年7月19日)的节目内容被删除了。

图4 删除F盘的数据
对于G和J盘来讲,该服务程序同样进行相同的操作,只不过删除的是G和盘(电视剧和电影频道)的内容而已。 就这样,每当新的一天到来时,该服务程序就开始检查F和H盘、G和J盘的剩余空间,并且进行相应的操作,随后把所进行的操作信息写在计算机的“事件查看器”当中。如果不人为删除,这些信息就一直保存在计算机当中。
三、结语 本例只是利用VB.NET编写Windows服务应用程序简单的具体实践,随着计算机技术的不断发展,利用VB.NET编写Windows服务程序会更加方便,功能会更强,更加完善。
|