.NET Framework中提供了现成的类库可以很方便的实现对windows服务的安装、卸载、启动、停止、获取运行状态等功能。这些类都在System.ServiceProcess命名空间下。

安装window服务

using (AssemblyInstaller installer = new AssemblyInstaller())
{
installer.UseNewContext = true;
installer.Path = serviceFilePath; //serviceFilePath是windows服务可执行文件的完整路径
IDictionary savedState = new Hashtable();
installer.Install(savedState);
installer.Commit(savedState);
}

卸载windows服务

using (AssemblyInstaller installer = new AssemblyInstaller())
{
installer.UseNewContext = true;
installer.Path = serviceFilePath;
installer.Uninstall(null);
}

启动windows服务

//使用ServiceController.GetServices()可获取windows服务列表,进而可判断服务是否存在

//serviceName是注册的windows服务名称

using (ServiceController control = new ServiceController(serviceName))
{
if (control.Status == ServiceControllerStatus.Stopped)
{
control.Start();
}
}

一切都似乎很简单,略坑的是,ServiceController.Start方法(注意并不是StartAsync),看起来是一个同步方法,如果服务启动失败,按理会异常抛出。而实际情况却时,Start方法是立即返回的,不会等待服务的启动结果。方法注释里发生异常只有两种情形:

System.ComponentModel.Win32Exception: 访问系统 API 时出错。

System.InvalidOperationException: 未找到服务。

至于其它情形导致的启动失败(如文件缺失、服务应用程序内部出错),Start方法一无所知。

ServiceController类有一个Wait方法,作用是阻塞当前线程等待服务到达指定的状态,还可以设置等待的超时时间,这有一定的用处,但并不理想。当启动失败的时候,如何能够获取到启动失败的信息呢?

一个猥琐的办法

windows服务启动无论成功还是失败,都会记录一条windows日志,可以借助对windows日志的监控来实现:

在调用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类的直接关联。

C#管理windows服务的更多相关文章

  1. 玩转Windows服务系列——命令行管理Windows服务

    说到Windows服务的管理就不得不说通过命令行的方式管理Windows服务,因为无论是系统管理员,还是通过编程的方式调用cmd命令,命令行都是非常方便以及强大的工具. 接下来就看一下如何通过cmd命 ...

  2. 玩转Windows服务系列——命令行管理Windows服务

    原文:玩转Windows服务系列——命令行管理Windows服务 说到Windows服务的管理就不得不说通过命令行的方式管理Windows服务,因为无论是系统管理员,还是通过编程的方式调用cmd命令, ...

  3. [转]玩转Windows服务系列——命令行管理Windows服务

    本文转自:http://www.cnblogs.com/hbccdf/p/managewindowsservicewithcmd.html 说到Windows服务的管理就不得不说通过命令行的方式管理W ...

  4. 如何使用PowerShell管理Windows服务

    [TechTarget中国原创] 作为一名系统管理员,最常见的任务之一就是学会管理Windows服务,这是保证Windows服务器和客户端正常运行的重要内容. 许多操作系统和应用程序都依赖于这些服务. ...

  5. 第十三篇 一个安装、管理windows服务的桌面程序

    在网上看到一个修改程序入口的程序去把windows 服务修改成控制台的程序,然后利用控制台的程序把服务安装和管理,也想起自己原来也写了一个对windows 报务管理的程序,不过是winform的.   ...

  6. Windows Server 2016-命令行方式管理Windows服务

    Microsoft Windows 服务(过去称为 NT 服务)允许用户创建可在其自身的 Windows 会话中长时间运行的可执行应用程序. 这些服务可在计算机启动时自动启动,可以暂停和重启,并且不显 ...

  7. python管理Windows服务

    上一篇介绍了pywin32模块,它的win32service子模块提供了对服务管理API的包装,相关API如下: ChangeServiceConfig ChangeServiceConfig2 Cl ...

  8. 使用Topshelf管理Windows服务

    目的:以控制台方式开发Windows服务程序,调试部署方便. https://www.cnblogs.com/itjeff/p/8316244.html https://www.cnblogs.com ...

  9. 玩转Windows服务系列汇总

    玩转Windows服务系列汇总 创建Windows服务 Debug.Release版本的注册和卸载及其原理 无COM接口Windows服务启动失败原因及解决方案 服务运行.停止流程浅析 Windows ...

随机推荐

  1. 13、Math类简介

    Math类概述 在java.lang包下,有个Math类,这个类包含用于执行基本数学运算的方法,如四舍五入,开方等等. package com.sutaoyu.usually_class; publi ...

  2. Linux下inittab文件详解

    /etc/inittab文件详解 Linux系统的启动过程为:加电自检-->根据BIOS中的设置从指定的设备启动-->找到设备MBR中的bootloader引导启动系统-->启动ke ...

  3. 【译】第七篇 SQL Server代理作业活动监视器

    本篇文章是SQL Server代理系列的第七篇,详细内容请参考原文 在这一系列的上一篇,你创建并配置SQL Server代理作业.每个作业有一个或多个步骤,可能包含大量的工作流.在这篇文章中,将查看作 ...

  4. 使用pandas把mysql的数据导入MongoDB。

    使用pandas把mysql的数据导入MongoDB. 首先说下我的需求,我需要把mysql的70万条数据导入到mongodb并去重, 同时在第二列加入一个url字段,字段的值和第三列的值一样,代码如 ...

  5. 2013 NEERC

    2013 NEERC Problem A. ASCII Puzzle 题目描述:完成一个拼图. solution 暴搜,但好像挺难打的,但听说因为题目限制比较多,其实很多奇怪的情况都不存在. Prob ...

  6. python socket编程和黏包问题

    一.基于TCP的socket tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端,有顺序,不重复,可靠.不会被加上数据边界. server端 import socket sk = so ...

  7. [HBase]mem store flusher 流程

  8. 【转】shell命令中>/dev/null 2>&1的实现原理

    异步执行 exec("/alidata/server/php/bin/php /nas/wxdoctor/index.php App/Common/WordsPic/user_id/&quo ...

  9. echarts一些笔记

    console.log();  浏览器显示 $.ajax({ url : "ajax/echartWelcome.action", type : "post", ...

  10. GLOBAL_NAMES参数研究

    最近在配置Stream时,发现必须要把GLOBAL_NAMES参数的指设置为TRUE,具体原因为何不知.但是发现在设置了该参数之后,数据库每天的物化视图刷新出现了问题.之后查明原因,是DBLINK出现 ...