Flikas 的个人资料Flikas' Space照片日志列表更多 ![]() | 帮助 |
|
|
2月7日 XML Web Service学习笔记 2 创建和管理Windows服务一、为什么使用Windows服务Windows服务是作为后台进程运行的。这些应用程序没有用户界面,适于处理不要求与用户交互的任务。Windows 服务应用程序在各自的安全上下文中运行,并且在用户登录到安装有该程序的 Windows 计算机之前启动。就是说,Windows服务可以在不同于当前登录用户的其他用户帐户安全上下文中运行,在系统帐户下运行的服务比在用户帐户下运行的服务具有更多的权限和特权。 综上所述,如果你的应用程序:
那么请选择Windows服务,否则,编写一个在用户控制下的Windows应用程序可能更为妥当,因为:
二、如果仍旧要编写Windows服务Windows服务体系结构:
再看一下.NET Framework提供的编程模型,所有相关的类都位于System.ServiceProcess命名空间:
三、编写Windows服务使用Visual Studio.NET编写Windows服务十分方便,虽然服务及其使用的事件日志组件和性能计数器组件都需要提供安装程序,但是只要单击属性窗口下方的“添加安装程序”选项,就可以自动完成安装程序的编写,相关设置都会被复制到安装程序中,但是,如果修改了原设置,安装程序中的设置不会跟着变化。 下面我要编写一个自己的服务应用程序,它的目的是监视硬盘上的临时文件夹的大小,并定期清理以节省磁盘空间。 Visutal Studio.NET提供了服务应用程序模板,使用这个模板生成服务应用程序,在Main()方法中,已经添加了类似如下的代码: System.ServiceProcess.ServiceBase[] ServicesToRun; ServiceBase.Run()方法用于把服务载入到内存,以便可以启动服务。 并且已经重写了OnStart和OnStop这两个方法,要编写最简单的服务应用程序,只要重写这两个方法就可以了。另外,ServiceBase类还有OnPause、OnContinue、OnShutDown、OnPowerEvent、OnCustomCommand这几个方法可供重写,在使用这些方法前,需要将类的CanPauseAndContinue、CanHandlePowerEvent、CanShutdown这几个属性设为True(默认为False),否则即使重写了方法也不会被执行。另外还有CanStop属性,如果将它设为false的话,这个服务甚至不能被停止。OnCustomCommand用于处理自定义命令,它的原型是: void OnCustomCommand(int command); 这就意味着除了指令本身不能传递任何参数,要传递其他信息就必须通过其他方式,如磁盘文件或注册表。 可以在应用程序中定义或在 OnCustomCommand 中使用的自定义命令的值只有 128 和 256 之间的值。128 以下的整数对应于系统保留的值。 如果Autolog属性为true,自定义命令就会像其他所有命令一样将项写入事件日志以报告方法执行是否成功。 1)使用EventLog组件输出信息因为服务应用程序无法与用户交互,我又添加了一个EventLog组件,可以在系统日志中写入一些调试信息等。EventLog组件有以下几个属性需要设置:
我的EventLog组件名称为eventLog,在程序中,就可以用eventLog.WriteEntry()方法在日志中写入信息了。 2)使用动态属性配置应用程序再拖动一个timer组件到程序集中,用于定时。在这里,注意到timer组件的定时时长应当是可以设置的,而服务应用程序无法与用户交互,那么如何使这个属性成为可配置的呢?动态属性很方便的解决了这个问题,只要在timer组件的属性窗口中,点击(DynamicPoperties)左边的加号,就可以看到timer控件默认可配置的属性Interval,点击将其映射到配置文件中就可以了。 然后,Visual Studio.NET将会生成app.config文件,这是一个XML类型的文件,在编译后他会重新被命名为程序集的名字,里面有类似如下的内容: <add key="timer.Interval" value="600000" /> 同时在设计器生成的InitializeComponents()方法中,初始化timer.Interval属性的语句也变成了: this.timer.Interval = ((System.Double)(configurationAppSettings.GetValue("timer.Interval", typeof(System.Double)))); 这样,每次启动程序的时候,都会从配置文件中载入这个属性的值。 这里的configurationAppSettings是一个System.Configuration.AppSettingsReader类型的对象,也可以使用System.Configuration.ConfigurationSettings类中的静态成员来获取配置文件中的值。 注意:配置文件是作为应用程序的一部分存在的,它只会在应用程序启动时被读取一次,也就是说,如果应用程序运行中,配置文件被修改,再使用System.Configuration命名空间中的类来读取值,也不能够读取到新的值。 3)编写核心部分核心部分的内容很少,只要在OnStart方法中启动timer,并在timer的Elapsed事件处理程序中检查临时文件夹的大小并删除没用的文件就可以了。 在编写中只遇到了一个问题,由于服务应用程序没有运行在当前登录的用户帐户下,所以无法用System.IO.Path.GetTempPath()获取当前登录用户的临时文件夹。我的解决方案仍然是使用app.config文件,只要在文件中添加一个新项TempDir,然后在程序载入这个值就可以了。配置文件可以由在用户帐户下运行的服务管理程序来修改。 我也重载了OnCustomCommand方法,在方法中设置了立即清理临时文件夹的命令。 4)添加安装程序服务必须先安装才能运行,前面已经介绍了添加安装程序的方法,由设计环境自动添加的安装程序就可以正确运行。需要修改的地方是:
在为服务以及服务使用的EventLog组件和PerformanceCounter组件都添加好安装程序后,就可以编译并安装应用程序了。 5)安装服务要安装服务,可以使用.NET安装实用程序Installutil,安装命令是: Installutil <.exe file> 同时还可以卸载应用程序,命令是: Installutil /u <.exe file> 下面是我安装服务时的输出: 安装后测试运行成功,下面两幅图中可以看到服务已经被添加进了SCM中,并在性能日志中建立了自己的日志类别并记录了信息。 四、调试Windows服务要调试Windows服务,需要启动服务,然后将调试器附加到服务所处的进程中,然后就可以像调试普通程序一样调试服务了。但是这样不能调试OnStart和Main方法,因为服务是在调试器被附加到服务进程以前启动的,要调试这两个方法,就需要创建测试套服务来帮助调试。 五、使用ServiceController管理Windows服务可以使用ServiceController类来管理和控制服务,它可以:
要查看计算机上服务的列表,可以使用GetServices方法;要运行自定义命令,可以使用ExecuteCommand方法。 注意:应当始终创建单独的应用程序,然后该程序包含ServiceController组件来控制应用程序。 下面是我编写的服务控制程序: 在这个程序中,我使用System.XML命名空间下的方法来读取和修改服务应用程序的配置文件,下面是读取设置部分的代码: XmlDocument configFile = new XmlDocument(); 类XmlDocument是W3C文档对象模型(DOM)的.NET实现,它将XML文档映射到一个树形结构上,它扩展自XmlNode这个递归定义的树节点,使用它的索引器可以方便的访问XML文档的各个元素。 我使用ServiceController的Start和Stop方法来启动和停止服务,下面是启动服务的代码: serviceController.Start(); 使用WaitForStatus方法可以阻塞当前线程等待服务达到某一个状态,还可以使用它的另一个重载方法来设置一个timeout。 “立即清理”按钮用于发送一个自定义命令至服务,只要使用ExecuteCommand方法并加上一个代表命令的int型参数即可,当然在发送指令前不要忘了检查服务的状态,向不在运行中的服务发出指令会引起InvalidOperationException: if (serviceController.Status == ServiceControllerStatus.Running) 引用通告此日志的引用通告 URL 是: http://flikas.spaces.live.com/blog/cns!FD1E577523FE041C!172.trak 引用此项的网络日志
|
|
|