.NET Framework中提供了现成的类库能够很方便的实现对windows服务的安装、卸载、启动、中止、获取运行状态等功能。这些类都在System.ServiceProcess命名空间下。windows
using (AssemblyInstaller installer = new AssemblyInstaller()) { installer.UseNewContext = true; installer.Path = serviceFilePath; //serviceFilePath是windows服务可执行文件的完整路径 IDictionary savedState = new Hashtable(); installer.Install(savedState); installer.Commit(savedState); }
using (AssemblyInstaller installer = new AssemblyInstaller()) { installer.UseNewContext = true; installer.Path = serviceFilePath; installer.Uninstall(null); }
//使用ServiceController.GetServices()可获取windows服务列表,进而可判断服务是否存在 //serviceName是注册的windows服务名称 using (ServiceController control = new ServiceController(serviceName)) { if (control.Status == ServiceControllerStatus.Stopped) { control.Start(); } }
一切都彷佛很简单,略坑的是,ServiceController.Start方法(注意并非StartAsync),看起来是一个同步方法,若是服务启动失败,按理会异常抛出。而实际状况却时,Start方法是当即返回的,不会等待服务的启动结果。方法注释里发生异常只有两种情形:spa
System.ComponentModel.Win32Exception: 访问系统 API 时出错。线程
System.InvalidOperationException: 未找到服务。日志
至于其它情形致使的启动失败(如文件缺失、服务应用程序内部出错),Start方法一无所知。code
ServiceController类有一个Wait方法,做用是阻塞当前线程等待服务到达指定的状态,还能够设置等待的超时时间,这有必定的用处,但并不理想。当启动失败的时候,如何可以获取到启动失败的信息呢?orm
windows服务启动不管成功仍是失败,都会记录一条windows日志,能够借助对windows日志的监控来实现:blog
在调用ServiceController.Start方法以前,启动对windows日志的监听:事件
_eventLog = new EventLog("Application"); _eventLog.EnableRaisingEvents = true; _eventLog.EntryWritten += Log_EntryWritten;
在EntryWritten事件处理器里,判断windows日志类型,进而得知windows服务启动状况:开发
private void Log_EntryWritten(object sender, EntryWrittenEventArgs e) { EventLogEntry log = e.Entry; if(log.Source == _currentSection.ServiceName) { if(log.EntryType == EventLogEntryType.Information) { //启动成功 } else { //启动失败 MessageBox.Show(log.Message); } _eventLog.Dispose(); _eventLog = null; } }
这里还一个略坑的点,按通常的事件开发约定,sender参数应该就是发生事件的主体,在这里想来应该就是EventLog类的实例,然而事实上sender是EventLogInternal类的实例,很遗憾的是,这个类并不公开访问,并且,也并未发现有跟EventLog类的直接关联。同步