1、服务介绍
操作系统在启动的时候,会启动一些不需要用户交互的进程。这些进程被称为服务。当操作系统启动后它就自动被运行。
2、组成
服务程序、服务控制程序(SCP,service control program)和服务控制管理器(SCM,service control manager)组成了Windows服务。我们可以通过SCP操纵SCM启动、暂停、停止服务程序。其中服务程序和SCP由我们自己编写。
SCM
servics.exe是操作系统内置的一个部件。建立数据库、启动服务(自启动),分配服务进程。
SCP
服务控制程序,例如windows自带的服务工具:

当然也可以自己写一个服务管理工具。
服务程序
我们需要执行的任务
3、执行原理
首先看看服务入口:
static void Main() { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new MainService() }; ServiceBase.Run(ServicesToRun); }
从入口看,这和控制台程序一样,因为绝大部分的服务都不需要交互,所以没有用户界面。 那么ServiceBase.Run到底做了什么事情呢?平常情况下,我们并不关心,只是windows服务听起来有点神秘。于是就搜索关于windows service原理的文章,理解一下。如下图:

大致原理:服务主线程调用StartServiceCtrlDispatcher,最终执行了ServiceMain回调,调用了我们自己写的服务代码。SCP通过CtrlHandle回调了我们对服务的一些操作,比如暂停,启动等等。它们都通过SetServiceStatus方法与SCM通信,把服务的状态等信息及时地告诉SCM。我结合代码主要介绍下,我们的服务代码是如何被调用的。
Main方法中的ServiceBase是一个什么样的类呢?


从继承关系上看,它是可以跨应用程序域调用(MarshalByRefObject——Enables access to objects across application domain boundaries in applications that support remoting)以及需要释放资源(IDisposable)。这说明,可以远程调用服务以及服务占用了非托管资源。
我们看Run方法:
1 public static void Run(ServiceBase[] services) 2 { 3 if ((services == null) || (services.Length == 0)) 4 { 5 throw new ArgumentException(Res.GetString("NoServices")); 6 } 7 if (Environment.OSVersion.Platform != PlatformID.Win32NT) 8 { 9 string message = Res.GetString("CantRunOnWin9x"); 10 string title = Res.GetString("CantRunOnWin9xTitle"); 11 LateBoundMessageBoxShow(message, title); 12 } 13 else14 { 15 IntPtr entry = Marshal.AllocHGlobal((IntPtr) ((services.Length + 1) * Marshal.SizeOf(typeof(System.ServiceProcess.NativeMethods.SERVICE_TABLE_ENTRY)))); 16 System.ServiceProcess.NativeMethods.SERVICE_TABLE_ENTRY[] service_table_entryArray = new System.ServiceProcess.NativeMethods.SERVICE_TABLE_ENTRY[services.Length]

