创建一个Windows Service应用程序

window|程序|创建

创建一个Windows Service应用程序
--------------------------------------------------------------------------------

下载本文代码
见资源

正是由于.NET Framework的出现,才使你能够构建出在系统重新启动时自动运行的、无人参与的(unattended)应用程序。
by Stan Schultes
技术工具箱:VB.NET, XML, ASP
Windows service应用程序曾经是C++程序员专用的领域,除非你在VB中使用了第三方工具。现在它们则成为System.ServiceProcess 命名空间下的.NET Framework类库中的主要部分,你可以随意使用任何.NET语言来构建它。Windows service是一种系统自动的、无人参与的程序(仅存在于Windows NT、2000和XP操作系统中),它能够在系统启动时开始运行。你可以通过Service Control Manager (SCM) applet或者一些特殊的service-control应用(utility)来访问Windows service。

我将讲解如何构建一个用于监控文件改变情况的Windows service。FileChangeMonitor service用于随意地编写事务日志(event-log)条目以及当文件在一段时间内没有改变时发送e-mail。这种文件监控过程在用于确保需要时进行备份、正常运转报告生成器或按时间表将文件传送到远程系统上时是非常有用的。FileChangeMonitor service还能够发送显示程序正常运行的综合报告。

第一步是构建一个作为将来service项目起始点的Windows service程序的模板。打开Visual Studio.NET,用Windows Service模板来创建一个新的项目,将其命名为FileChangeMonitor(点此下载范例代码)。鼠标右键单击Solution Explorer(SE)中的Service1.vb文件并将其重新命名为ChangeMonitor.vb。点击ChangeMonitor 设计界面(你会看到“To add components to your class”消息),并将其在属性窗口(按F4显示的窗口)中的的名字和ServiceName属性均改为ChangeMonitor。

同样将属性窗口中的CanPauseAndContinue和CanShutdown属性值设置为True。 这些属性控制着该service程序是否能够暂停/继续,以及在系统关闭时是否做出响应。你将在后面使用这些事件(以及Stop事件)来保存你的service的“状态”――即给定时间内的执行文本(execution context )。

接下来,点击ChangeMonitor 设计窗口中的“click here to switch to code view”链接。在代码窗口中,点击左边的加号来打开名为“Component Designer generated code”的区域。在Sub Main过程(routine)中,将ServicesToRun 赋值语句中的Service1改为ChangeMonitor: ServicesToRun = New System. _
   ServiceProcess.ServiceBase() _
   {New ChangeMonitor()}

右键单击在SE中的FileChangeMonitor项目,选中属性,再从StartupObject下拉列表中选择Sub Main。现在你就可以开始构建你的项目了(通过使用Build | Build Solution菜单项)。

创建事件模板和过程
现在,在模板中加入一些事件过程(event-routine)的原型。你等一会儿可以将代码添加到这些service事件中去以便处理 Windows service程序中的状态变化。在代码窗口中点击Class Name combo box(位于代码窗口上面左侧的combo box),然后选中(Overrides)选项。在Method Name combo box中(位于代码窗口上面右侧的combo box),依次选中各项以便将过程原型(一个空程序)添加到代码窗口中,比如:OnContinue、OnPause和OnShutdown。你必须在每个过程中的Method Name combo box中重新选择(Overrides)选项 。

接下来就开始构建过程模板。在你需要添加代码的ChangeMonitor.vb中创建五个子过程原型: LoadSettings()、SaveSettings()、RunCheck()、RunSummary()和StartService()。在这个类的最顶部Imports System.ServiceProcess语句的下面,通过使用Imports语句来添加其他需要用到的命名空间:Imports System.IO
Imports System.Timers
Imports System.Web.Mail
Imports System.Reflection
Imports System.Xml.Serialization

由于你的service应用程序不是一个Web项目,因此你可能需要手动将一个引用(reference)添加到Web.Mail命名空间下。右键单击SE中的FileChangeMonitor项目,从弹出菜单中选择Add Reference。在 Add Reference对话框中选择列表中的System.Web.dll条目,单击Select按钮,然后点OK。

在ChangeMonitor类的顶部、Component Designer区域的前面,添加一个用于文件检查功能的Timer对象的声明: Private WithEvents ControlTimer As Timer

然后将下面三行代码加到OnStart和OnContinue事件程序中: StartService()
RunCheck()
RunSummary()

当你的service启动时会触发OnStart事件,而当暂停后继续运行时则会触发OnContinue事件。

在Class Name combo box中选择ControlTimer,并在Method Name combo box中选择Elapsed。这样就会将ControlTimer_Elapsed事件过程原型添加到项目中了。只需添加这两个Run语句到ControlTimer_Elapsed事件过程中,然后在OnPause、OnShutdown和OnStop事件过程中添加代码来中断计时器(Timer)并保存设置: ControlTimer.Stop()
SaveSettings()

从这个简单的程序大纲中你可以看到用于Windows service应用程序的文件检查功能的控制流程是如何运作的。当其中一个事件触发时,StartService函数便会加载设置,然后运行文件和简要检查。你可以在计时器时间到时运行检查程序;可以用stop或pause事件来中断计时器以及保存设置。

在StartService过程中添加代码来创建计时器,将时间间隔定为15秒(以毫秒值计),然后启动它:ControlTimer = New Timer()
ControlTimer.Interval = 15000
ControlTimer.AutoReset = True
ControlTimer.Start()

AutoReset = True属性设定使计时器在时间到时继续运行。接下来,你可以在check函数运行时添加代码来编写Windows Application事务日志,这样你就可以看到service正在运行: Private Sub RunCheck()
   EventLog.WriteEntry(ServiceName & _
      " - Check", "Checking Files.")
End Sub

你可以通过Windows中的Event Viewer(EV)应用程序来查看事件日志中的消息。

添加一个安装程序(Installer)
创建service应用程序模板的最后一项工作是在项目中添加一个安装程序。在它运行之前你需要首先注册这个Windows service程序。切换到ChangeMonitor设计界面并打开属性窗口(如果看不到的话可以按F4),你可以看到在属性窗口下面有一个名为Add Installer的链接,点击该链接后会出现一个向导来引导你将一个名为ProjectInstaller的组件添加到当前项目中。这个向导在ProjectInstaller设计界面中放置了两个service控件:ServiceProcessInstaller和ServiceInstaller。

图1. 设置Service属性
点击ServiceProcessInstaller控件并对Account属性进行设置。你可能希望选择LocalSystem(大多数service是运行在LocalSystem中的),但如果你喜欢,你还可以将它设置为一个用户帐户。点击ServiceInstaller,将它的属性设置为DisplayName = FileChangeMonitor、 ServiceName = ChangeMonitor以及StartType = Automatic(如果你希望通过手动启动该service的话也可以将它设置为Manual)。

通过Build | Build Solution来构建你自己的项目,确保不存在什么错误。现在你就可以使用一个名为InstallUtil的Framework应用来安装你的service了。打开命令行提示(command-prompt)窗口并执行corvars.bat文件来设置环境变量(你可以下载readme文件来了解详细内容)。使用cd(change directory)命令将其导航到你项目中的\bin目录下。执行以下命令来安装你的service:> InstallUtil filechangemonitor.exe

现在你可以使用Control Panel的Administrative Tools菜单(Win2K 和WinXP操作系统)中的SCM applet来启动、停止、暂停以及继续运行你的FileChangeMonitor service了 (见图1)。当你启动这个service后就可以使用EV来查看Application事务日志中由该service生成的事件了。点击F5刷新EV的显示,你会看到“Check messages every 15 seconds”。你可以使用以下命令来卸载这个service(先用SCM来终止service): > InstallUtil filechangemonitor.exe /u

现在你可以保存该项目并将它作为以后service程序的一个模板。

Service以某种状态运行(这可能是它未运行时保存的一组设定)。当service重新启动时,你可以加载它上次运行时的状态。一个简便的方法是使用.NET Framework中的序列化类(serialization class),如System.Xml.Serialization命名空间下的XML序列化(你也可以选择binary和SOAP序列化)。

用XML序列化保存设置
XML序列化是和用<Serializable()>属性标记的类配合使用的。右键单击SE中的FileChangeMonitor项目,从弹出的菜单中选择Add | Add Class,将该类命名为CMonitor并点击 OK。在CMonitor中添加两个类――MonitorHeader和MonitorFile: <Serializable()> Public Class MonitorHeader
   Public MonitorIntSecs As Integer
   '<other header properties>
   Public Files() As MonitorFile
End Class
<Serializable()> Public Class MonitorFile
   Public Path As String
   '<other file properties>
End Class

MonitorHeader包含控制service的设置,包括一组MonitorFile对象。MonitorFile对象中包含每个你想要检查进度的文件的监控设置。你可以将大多数类的属性当作Public变量来实现,因为它们只用于你的service项目中。查看范例代码来了解该类的完整定义。你可以在ChangeMonitor 类的模块中实现LoadSettings和SaveSettings序列化过程(见列表1)。

在用于声明设置对象和存储设置文件路径的ChangeMonitor类的顶部添加该类的私有变量:Private m_MonitorControl As New _
   MonitorHeader()
Private m_sSettingsPath As String

在调用StartService()之前将代码添加到OnStart过程中,来完成在service启动之前对设置文件名进行检测。用Reflection来找到应用程序的runtime .exe路径,并用substitute .xml作为文件的扩展名(这两个文件在同一目录下): m_sSettingsPath = [Assembly]. _
   GetEntryAssembly.Location. _
   Replace(".exe", ".xml")

在VB.NET中assembly是一个关键字,因此在代码中你必须把它用一个方括号括起来。你需要整理StartService()过程以便从设置文件中加载计时器间隔: If m_MonitorControl _
   .MonitorIntervalSecs > 0 Then
   ControlTimer.Interval = _
      Ctype(m_MonitorControl _
      .MonitorIntervalSecs * 1000, Double)
   ControlTimer.AutoReset = True
   ControlTimer.Start()
End If

现在,你可以实现主要的检查函数――RunCheck了(见列表2)。RunCheck负责调用RunAlarmAction并计算出Files数组中每个文件的出现次数,该文件的NextCheck代表的是当前时间之前的时间并且自从上次检查以后就没有发生过改变。RunAlarmAction负责检查AlarmAction标记、编写事务日志,然后通过SendEmail过程来发送e-mail (见列表3)。

你可以采用类似的方法,基于MonitorHeader结构的汇总设置(summary setting)来实现RunSummary和RunSummaryAction方法,构建并测试你的Windows service应用程序。范例代码中还包括一个名为FileChgCtl的service-control应用。它主要用于调试目的,可以将自定义命令(custom command)发送到FileChangeMonitor service中。自定义命令是一个范围在128到255之间的整数。当Windows service应用程序中的OnCustomCommand事件触发时你会得到自定义命令出现的通知。

你会发现service 应用程序在很多情况下是非常有用的,比如用在系统维护、监控以及其他自动的、无人照顾的操作中。Windows service通常会通过事务日志来记录其活动情况,但正如我所介绍的,你的service也可以通过发送e-mail来方便地跟踪其进展情况。构建Windows service应用程序的能力使你在用Windows构建有效的商务方案方面得以轻松地扩展。

关于作者:
Stan Schultes 是Florida州Sarasota地区的一名Web和企业应用程序的架构师和开发人员,以及VB开发领域的MCP。Stan是VSM的一名特约编辑,定期为该杂志撰写文章。你可以访问Stan的网站www.vbnetexpert.com查看在线代码演示、更新资料以及其他信息。他的e-mail地址是stan@vbnetexpert.com。

时间: 2024-12-06 16:16:16

创建一个Windows Service应用程序的相关文章

在Azure中创建一个“Hello World”应用程序

在本文中,我们将会讨论如何使用.NET在Azure中创建一个"Hello World!!!"应用程序.我使用安装了Azure SDK 1.3的Visual Studio 2010.启动Visual Studio,然后创建一个新项目.在"Cloud"模板中选择"Windows Azure Cloud Service". 点击了"OK"以后,它会让你选择一个"Role".这里,我们添加了一个ASP.Net We

使用 Microsoft.NET Frameworks 创建基于 Windows 的应用程序(转)

摘要: :本文介绍了 Win 表单这一新的窗体程序包,借助这一程序包,开发人员能够充分利用 Microsoft Windows 操作系统所提供的 UI 功能.目录 简介 介绍 Win Forms 更好的易学易用性 布局 GDI+ 访问底层系统 结论 --------------------------------------------------------------------------------简介 目前 Web 已成了街谈巷议的话题,看起来好像 Microsoft Visual S

用C#在本地创建一个Windows帐户(DOS命令)_C#教程

其它方法见.用C#在本地创建一个Windows帐户(DirectoryServices)  http://yaosansi.com/blog/article.asp?id=917    在WinForm下该程序可写成:   (已测试通过,需要以Administrator身份运行)       using   System;       namespace   eg       {       class     test       {       static     void     Mai

用EclipseME0.5.5创建一个简单的J2ME程序

程序|创建 用EclipseME0.5.5创建一个简单的J2ME程序 上一篇文章<如何在Eclipse3.0.1上安装EclipseME 0.5.5版本>,我们已经讲了如何在Eclipse3.0.1上安装Eclipse程序. 今天我们就要用他来创建我们的第一个程序.绝大多数程序教程的第一个程序,都叫做HelloWorld.那么我们就来编一个HelloWorld程序. 1, 文件2, 新建项目3, 选择J2ME,J2ME Midlet Suite4, 输入项目名称:MyFirstJ2ME5, 选

windows编程-关于一个windows service的问题

问题描述 关于一个windows service的问题 下面一段是winform的代码,能否转换成Windows service的吗? Main.cs public partial class Main : Form { private readonly InterfaceDll _interface; public Main() { InitializeComponent(); _interface = new InterfaceDll(Handle, Application.StartupP

怎么样创建一个扩展控件程序?

问题描述 本人一菜鸟正在学习控件使用技术.想咨询一下各位,如何创建一个扩展控件程序,我想将我自己写的扩展控件添加到工具栏中使用.我看一个教程说是"新建项目的时候添加一个类库"对吗?请各出具体操作方法的步骤,当然越简单越好吧,谢谢! 解决方案 解决方案二:1.可以用userControl2.写一个类,继承自系统控件就是.解决方案三:up解决方案四:说的有点抽象...解决方案五:楼主是想做VS插件解决方案六:http://download.csdn.net/detail/yanele/39

How to Create a Windows NT/ Windows 2000 Service(如何创建一个Windows NT/ Windows 2000 服务)

Introduction A Windows service is an EXE specially designed to communicate with the SCM (Service Control Manager) of Windows NT/2000. The Service Control Manager (SCM) maintains a database of installed services and driver services, and provides a uni

我的WCF之旅(1):创建一个简单的WCF程序

写在前面 在Microsoft提出.NET战略以来, 先后推出了一系列产品和技术, 这些产品和技术为我们在.NET平台下建立企业级的分布式应用提供了很大的 便利.这些技术和产品包括:.NET Remoting,XML WebSerivce,WSE(2.0,3.0),Enterprise Service, MSMQ ...... 我们知道,和一个相对独立的应用不同,我们开发一个分布式应用, 尤其是开发一个企业级的分布式应用, 我们需要考虑较多的东西.比如我们要考虑数据在不同的应用之间传递时采取什么

教你创建一个Windows 8可启动的USB闪盘

动因 到了公司,恰巧一个同事和我说他做的Windows to Go的windows 8启动盘不好用,记得前一段我也用个64GB3.0的USB,然后用Imagex 做过一个,但是貌似启动状态属于段誉的六脉神剑,时灵时不灵的,因此这里就小小研究了一下,小小分享一下,希望对做闪盘启动感兴趣的你有所帮助. 正题 我们有时候为了方便或者用于临时环境演示或者需要临时借用其他人的计算机又不想破坏人家的现有环境,可能会想到一个取巧的方法,那就是通过制作一个用USB闪盘制作的Windows 8系统,这样快捷方便U