将作为一个服务应用程序的一部分存在的服务提供基类。 ServiceBase 必须派生自创建新的服务类时。
程序集: System.ServiceProcess(位于 System.ServiceProcess.dll)
System.MarshalByRefObject
System.ComponentModel.Component
System.ServiceProcess.ServiceBase
名称 | 说明 | |
---|---|---|
ServiceBase() |
创建 ServiceBase 类的新实例。 |
名称 | 说明 | |
---|---|---|
AutoLog |
指示是否报表在事件日志中的启动、 停止、 暂停和继续命令。 |
|
CanHandlePowerEvent |
获取或设置一个值,该值指示服务是否可以处理计算机电源状态更改的通知。 |
|
CanHandleSessionChangeEvent |
获取或设置一个值,指示服务是否可以处理会话从终端服务器会话接收到的更改事件。 |
|
CanPauseAndContinue |
获取或设置一个值,该值指示是否可以暂停和恢复该服务。 |
|
CanRaiseEvents |
获取一个值,该值指示组件是否可以引发一个事件。(继承自 Component。) |
|
CanShutdown |
获取或设置一个值,该值在系统关闭时是否应通知服务。 |
|
CanStop |
获取或设置一个值,指示它启动后是否可以停止服务。 |
|
Container |
获取 IContainer ,其中包含 Component。(继承自 Component。) |
|
DesignMode | ||
EventLog |
获取可用于写入应用程序事件日志服务命令调用,如启动和停止通知事件日志。 |
|
Events | ||
ExitCode |
获取或设置该服务的退出代码。 |
|
ServiceHandle |
获取服务的服务控制句柄。 |
|
ServiceName |
获取或设置用于标识服务对系统的短名称。 |
|
Site |
名称 | 说明 | |
---|---|---|
CreateObjRef(Type) |
创建包含所有生成代理用于与远程对象进行通信所需的相关信息的对象。(继承自 MarshalByRefObject。) |
|
Dispose() | ||
Dispose(Boolean) |
处置由 ServiceBase 占用的资源(内存除外)。(覆盖 Component.Dispose(Boolean)。) |
|
Equals(Object) |
确定指定的对象是否等于当前对象。(继承自 Object。) |
|
Finalize() | ||
GetHashCode() |
作为默认哈希函数。(继承自 Object。) |
|
GetLifetimeService() |
检索当前生存期服务对象,用于控制此实例的生存期策略。(继承自 MarshalByRefObject。) |
|
GetService(Type) | ||
GetType() | ||
InitializeLifetimeService() |
获取生存期服务对象来控制此实例的生存期策略。(继承自 MarshalByRefObject。) |
|
MemberwiseClone() | ||
MemberwiseClone(Boolean) |
创建当前的浅表副本MarshalByRefObject对象。(继承自 MarshalByRefObject。) |
|
OnContinue() |
在派生类中实现时 OnContinue 时继续命令发送到服务的服务控制管理器 (SCM) 运行。 指定当某个服务后继续正常工作正在暂停时要执行的操作。 |
|
OnCustomCommand(Int32) |
在派生类中实现时 OnCustomCommand 服务控制管理器 (SCM) 向服务传递自定义命令时执行。 指定具有指定的参数值的命令发生时要采取的操作。 |
|
OnPause() |
派生类中实现时,暂停命令发送到服务的服务控制管理器 (SCM) 时执行。 指定当服务就会暂停时要执行的操作。 |
|
OnPowerEvent(PowerBroadcastStatus) |
派生类中实现时,在计算机的电源状态已发生更改时执行。 这适用于便携式计算机,当他们进入挂起模式,这不是系统关闭相同。 |
|
OnSessionChange(SessionChangeDescription) |
在终端服务器会话中接收的更改事件时执行。 |
|
OnShutdown() |
派生类中实现时,在系统关闭时执行。 指定在系统关闭之前应该发生什么。 |
|
OnStart(String[]) |
派生类中实现时,在由服务控制管理器 (SCM) 或在操作系统启动时 (对于自动启动的服务) 时,将启动命令发送到服务时执行。 指定当服务启动时要执行的操作。 |
|
OnStop() |
派生类中实现时,停止命令发送到服务的服务控制管理器 (SCM) 时执行。 指定当服务停止运行时要执行的操作。 |
|
RequestAdditionalTime(Int32) |
挂起的操作的请求更多时间。 |
|
Run(ServiceBase) |
与服务控制管理器 (SCM) 注册服务的可执行文件。 |
|
Run(ServiceBase[]) |
注册多个服务的可执行文件与服务控制管理器 (SCM)。 |
|
ServiceMainCallback(Int32, IntPtr) |
此 API 支持 产品 基础结构,不应从代码直接使用。 注册命令处理程序,然后启动该服务。 |
|
Stop() |
停止正在执行的服务。 |
|
ToString() |
名称 | 说明 | |
---|---|---|
MaxNameLength |
指示服务名称的最大大小。 |
派生自 ServiceBase 在服务应用程序中定义您的服务类时。 任何有用的服务的替代 OnStart 和 OnStop 方法。 对于其他功能,您可以重写 OnPause 和 OnContinue 用特定行为的服务状态变化。
服务是长时间运行的可执行文件不支持用户界面,并可能无法在已登录的用户帐户下运行。 该服务可以没有任何登录到计算机的用户的情况下运行。
默认情况下,服务不是管理员帐户相同的系统帐户下运行。 不能更改系统帐户的权限。 或者,可以使用 ServiceProcessInstaller 来指定将在其下运行服务的用户帐户。
一个可执行文件可以包含多个服务,但必须包含一个单独 ServiceInstaller 为每个服务。 ServiceInstaller 实例向系统注册该服务。 安装程序还将每个服务与事件日志用于记录服务命令相关联。 main() 函数可执行文件中的定义的服务应该运行。 该服务的当前工作目录是系统目录中,不是可执行文件所在的目录。
当您启动服务时,系统查找可执行文件,并运行 OnStart 可执行文件中包含该服务的方法。 但是,运行该服务不是运行可执行文件一样。 可执行文件仅加载服务。 访问此服务时 (例如,启动和停止) 通过服务控制管理器。
可执行文件调用 ServiceBase 派生类的第一个构造函数时调用该服务上的启动。 OnStart 构造函数执行后立即调用命令处理方法。 构造函数不会执行加载服务后,在首次后再次因此有必要单独的由中执行的构造函数执行的处理 OnStart。 可以通过释放任何资源 OnStop 应中创建 OnStart。 在构造函数中创建资源会阻止他们正在正确创建,如果服务启动后再次 OnStop 具有已释放的资源。
服务控制管理器 (SCM) 使您能够与服务交互。 SCM 可用于将开始、 停止、 暂停、 继续或自定义命令传递到服务。 SCM 使用的值 CanStop 和 CanPauseAndContinue 来确定服务是否接受停止、 暂停或继续命令。 停止、 暂停和继续在 SCM 的上下文菜单才中启用相应的属性 CanStop 或 CanPauseAndContinue 是 true 在服务类中。 如果启用,则将命令传递到服务,并 OnStop, ,OnPause, ,或 OnContinue 调用。 如果CanStop, ,CanShutdown, ,或 CanPauseAndContinue 是 false, ,相应的命令处理方法 (如 OnStop) 将不会处理,即使您已实现该方法。
您可以使用 ServiceController 类以编程方式执行 SCM 未使用的用户界面。 您可以自动化可在控制台中执行的任务。 如果 CanStop, ,CanShutdown, ,或 CanPauseAndContinue 是 true 但尚未实现相应的命令处理方法 (如 OnStop) 系统引发异常,并将忽略该命令。
不需要实现 OnStart, ,OnStop, ,或在任何其他方法 ServiceBase。 但是,该服务的行为详见 OnStart, ,因此,在最低限度下,应重写该成员。main() 函数的可执行文件中注册服务可执行文件使用服务控制管理器中,通过调用 Run 方法。 ServiceName 属性 ServiceBase 对象传递给 Run 方法必须与匹配 ServiceName 该服务的服务安装程序的属性。
您可以使用 InstallUtil.exe 若要在您的系统上安装服务。
自 1.1 起可用
此类型的所有公共静态(Visual Basic 中的 已共享 在 Visual Basic 中)成员都是线程安全的。不保证所有实例成员都是线程安全的。
ServiceBase 类
命名空间:System.ServiceProcess
程序集:System.ServiceProcess(在 system.serviceprocess.dll 中)
当在服务应用程序中定义服务类时从 ServiceBase 派生。任何有用的服务均将重写 OnStart 和 OnStop 方法。对于其他功能,可以用特定行为重写 OnPause 和 OnContinue 来响应服务状态的更改。
服务是长时间运行的可执行文件,它不支持用户界面,在登录的用户帐户下可能无法运行。服务可以在没有任何用户登录计算机的情况下运行。
默认情况下,服务在“系统”帐户下运行,该帐户与“管理员”帐户不同。不能更改“系统”帐户的权限。或者,可以使用 ServiceProcessInstaller 指定运行服务时将使用的用户帐户。
一个可执行文件可以包含多项服务,但对每项服务均必须包含一个单独的 ServiceInstaller。ServiceInstaller 实例在系统中注册服务。安装程序还将每项服务与一个事件日志关联,您可以使用该日志记录服务命令。可执行文件中的 main() 函数定义哪些服务应该运行。服务的当前工作目录是系统目录,而不是可执行文件所位于的目录。
当启动某项服务时,系统将定位相应的可执行文件,并运行该服务的 OnStart 方法(它包含在可执行文件内)。但是,运行服务与运行可执行文件并不相同。可执行文件仅加载服务。服务则通过“服务控制管理器”访问(例如启动和停止)。
当您对服务首次调用“开始”时,可执行文件调用 ServiceBase 派生类的构造函数。在构造函数执行之后将立即调用 OnStart 命令处理方法。在服务首次加载之后,构造函数不会再次执行,因此有必要将构造函数执行的处理和 OnStart 执行的处理分开。可以由 OnStop 释放的任何资源都应在 OnStart 中创建。如果服务在 OnStop 释放资源后再次启动,那么,在构造函数中创建资源会妨碍这些资源的正确创建。
“服务控制管理器”(SCM) 提供与服务交互的方式。可以使用 SCM 将“开始”(Start)、“停止”(Stop)、“暂停”(Pause)、“继续”(Continue) 或自定义命令传递到服务中。SCM 使用 CanStop 和 CanPauseAndContinue 的值,决定服务是否接受“停止”、“暂停”或“继续”命令。仅当服务类中相应的属性 CanStop 或 CanPauseAndContinue 为 true 时,才会在 SCM 的上下文菜单中启用“停止”、“暂停”或“继续”。如果已启用,则相应的命令将传递到服务,并且调用 OnStop、OnPause 或 OnContinue。如果 CanStop、CanShutdown 或 CanPauseAndContinue 为 false,则即使已实现相应的命令处理方法(如 OnStop),也不会予以处理。
可以使用 ServiceController 类通过编程实现 SCM 使用用户界面实现的功能。可以自动处理控制台中可用的任务。如果 CanStop、CanShutdown 或 CanPauseAndContinue 为 true,但尚未实现相应的命令处理方法(如 OnStop),则系统引发异常并忽略该命令。
不必在 ServiceBase 中实现 OnStart、OnStop 或其他任何方法。然而,服务的行为在 OnStart 中加以描述,因此至少应重写该成员。必须在可执行文件的 main() 函数中设置服务的服务名称。在 main() 中设置的服务名称必须与服务安装程序的 ServiceName 属性完全匹配。
可以使用 InstallUtil.exe 在系统中安装服务。
1 // Turn on logging to the event log. 2 #define LOGEVENTS 3 4 using System; 5 using System.IO; 6 using System.Threading; 7 using System.Collections.Generic; 8 using System.ComponentModel; 9 using System.Data; 10 using System.Diagnostics; 11 using System.ServiceProcess; 12 using System.Text; 13 using Microsoft.Win32; 14 using System.Runtime.InteropServices; 15 using System.Windows.Forms; 16 17 namespace ServiceSample 18 { 19 // Define custom commands for the SimpleService. 20 public enum SimpleServiceCustomCommands { StopWorker = 128, RestartWorker, CheckWorker }; 21 [StructLayout(LayoutKind.Sequential)] 22 public struct SERVICE_STATUS 23 { 24 public int serviceType; 25 public int currentState; 26 public int controlsAccepted; 27 public int win32ExitCode; 28 public int serviceSpecificExitCode; 29 public int checkPoint; 30 public int waitHint; 31 } 32 33 public enum State 34 { 35 SERVICE_STOPPED = 0x00000001, 36 SERVICE_START_PENDING = 0x00000002, 37 SERVICE_STOP_PENDING = 0x00000003, 38 SERVICE_RUNNING = 0x00000004, 39 SERVICE_CONTINUE_PENDING = 0x00000005, 40 SERVICE_PAUSE_PENDING = 0x00000006, 41 SERVICE_PAUSED = 0x00000007, 42 } 43 44 // Define a simple service implementation. 45 public class SimpleService : System.ServiceProcess.ServiceBase 46 { 47 private static int userCount = 0; 48 private static ManualResetEvent pause = new ManualResetEvent(false); 49 50 [DllImport("ADVAPI32.DLL", EntryPoint = "SetServiceStatus")] 51 public static extern bool SetServiceStatus( 52 IntPtr hServiceStatus, 53 SERVICE_STATUS lpServiceStatus 54 ); 55 private SERVICE_STATUS myServiceStatus; 56 57 private Thread workerThread = null; 58 59 public SimpleService() 60 { 61 CanPauseAndContinue = true; 62 CanHandleSessionChangeEvent = true; 63 ServiceName = "SimpleService"; 64 } 65 66 static void Main() 67 { 68 #if LOGEVENTS 69 EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() + 70 " - Service main method starting..."); 71 #endif 72 73 // Load the service into memory. 74 System.ServiceProcess.ServiceBase.Run(new SimpleService()); 75 76 #if LOGEVENTS 77 EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() + 78 " - Service main method exiting..."); 79 #endif 80 81 } 82 83 private void InitializeComponent() 84 { 85 // Initialize the operating properties for the service. 86 this.CanPauseAndContinue = true; 87 this.CanShutdown = true; 88 this.CanHandleSessionChangeEvent = true; 89 this.ServiceName = "SimpleService"; 90 } 91 92 // Start the service. 93 protected override void OnStart(string[] args) 94 { 95 IntPtr handle = this.ServiceHandle; 96 myServiceStatus.currentState = (int)State.SERVICE_START_PENDING; 97 SetServiceStatus(handle, myServiceStatus); 98 99 // Start a separate thread that does the actual work. 100 101 if ((workerThread == null) || 102 ((workerThread.ThreadState & 103 (System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0)) 104 { 105 #if LOGEVENTS 106 EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() + 107 " - Starting the service worker thread."); 108 #endif 109 110 workerThread = new Thread(new ThreadStart(ServiceWorkerMethod)); 111 workerThread.Start(); 112 } 113 if (workerThread != null) 114 { 115 #if LOGEVENTS 116 EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() + 117 " - Worker thread state = " + 118 workerThread.ThreadState.ToString()); 119 #endif 120 } 121 myServiceStatus.currentState = (int)State.SERVICE_RUNNING; 122 SetServiceStatus(handle, myServiceStatus); 123 124 } 125 126 // Stop this service. 127 protected override void OnStop() 128 { 129 // New in .NET Framework version 2.0. 130 this.RequestAdditionalTime(4000); 131 // Signal the worker thread to exit. 132 if ((workerThread != null) && (workerThread.IsAlive)) 133 { 134 #if LOGEVENTS 135 EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() + 136 " - Stopping the service worker thread."); 137 #endif 138 pause.Reset(); 139 Thread.Sleep(5000); 140 workerThread.Abort(); 141 142 } 143 if (workerThread != null) 144 { 145 #if LOGEVENTS 146 EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() + 147 " - OnStop Worker thread state = " + 148 workerThread.ThreadState.ToString()); 149 #endif 150 } 151 // Indicate a successful exit. 152 this.ExitCode = 0; 153 } 154 155 // Pause the service. 156 protected override void OnPause() 157 { 158 // Pause the worker thread. 159 if ((workerThread != null) && 160 (workerThread.IsAlive) && 161 ((workerThread.ThreadState & 162 (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) == 0)) 163 { 164 #if LOGEVENTS 165 EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() + 166 " - Pausing the service worker thread."); 167 #endif 168 169 pause.Reset(); 170 Thread.Sleep(5000); 171 } 172 173 if (workerThread != null) 174 { 175 #if LOGEVENTS 176 EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() + 177 " OnPause - Worker thread state = " + 178 workerThread.ThreadState.ToString()); 179 #endif 180 } 181 } 182 183 // Continue a paused service. 184 protected override void OnContinue() 185 { 186 187 // Signal the worker thread to continue. 188 if ((workerThread != null) && 189 ((workerThread.ThreadState & 190 (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) != 0)) 191 { 192 #if LOGEVENTS 193 EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() + 194 " - Resuming the service worker thread."); 195 196 #endif 197 pause.Set(); 198 } 199 if (workerThread != null) 200 { 201 #if LOGEVENTS 202 EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() + 203 " OnContinue - Worker thread state = " + 204 workerThread.ThreadState.ToString()); 205 #endif 206 } 207 } 208 209 // Handle a custom command. 210 protected override void OnCustomCommand(int command) 211 { 212 #if LOGEVENTS 213 EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() + 214 " - Custom command received: " + 215 command.ToString()); 216 #endif 217 218 // If the custom command is recognized, 219 // signal the worker thread appropriately. 220 221 switch (command) 222 { 223 case (int)SimpleServiceCustomCommands.StopWorker: 224 // Signal the worker thread to terminate. 225 // For this custom command, the main service 226 // continues to run without a worker thread. 227 OnStop(); 228 break; 229 230 case (int)SimpleServiceCustomCommands.RestartWorker: 231 232 // Restart the worker thread if necessary. 233 OnStart(null); 234 break; 235 236 case (int)SimpleServiceCustomCommands.CheckWorker: 237 #if LOGEVENTS 238 // Log the current worker thread state. 239 EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() + 240 " OnCustomCommand - Worker thread state = " + 241 workerThread.ThreadState.ToString()); 242 #endif 243 244 break; 245 246 default: 247 #if LOGEVENTS 248 EventLog.WriteEntry("SimpleService.OnCustomCommand", 249 DateTime.Now.ToLongTimeString()); 250 #endif 251 break; 252 } 253 } 254 // Handle a session change notice 255 protected override void OnSessionChange(SessionChangeDescription changeDescription) 256 { 257 #if LOGEVENTS 258 EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + 259 " - Session change notice received: " + 260 changeDescription.Reason.ToString() + " Session ID: " + 261 changeDescription.SessionId.ToString()); 262 #endif 263 264 switch (changeDescription.Reason) 265 { 266 case SessionChangeReason.SessionLogon: 267 userCount += 1; 268 #if LOGEVENTS 269 EventLog.WriteEntry("SimpleService.OnSessionChange", 270 DateTime.Now.ToLongTimeString() + 271 " SessionLogon, total users: " + 272 userCount.ToString()); 273 #endif 274 break; 275 276 case SessionChangeReason.SessionLogoff: 277 278 userCount -= 1; 279 #if LOGEVENTS 280 EventLog.WriteEntry("SimpleService.OnSessionChange", 281 DateTime.Now.ToLongTimeString() + 282 " SessionLogoff, total users: " + 283 userCount.ToString()); 284 #endif 285 break; 286 case SessionChangeReason.RemoteConnect: 287 userCount += 1; 288 #if LOGEVENTS 289 EventLog.WriteEntry("SimpleService.OnSessionChange", 290 DateTime.Now.ToLongTimeString() + 291 " RemoteConnect, total users: " + 292 userCount.ToString()); 293 #endif 294 break; 295 296 case SessionChangeReason.RemoteDisconnect: 297 298 userCount -= 1; 299 #if LOGEVENTS 300 EventLog.WriteEntry("SimpleService.OnSessionChange", 301 DateTime.Now.ToLongTimeString() + 302 " RemoteDisconnect, total users: " + 303 userCount.ToString()); 304 #endif 305 break; 306 case SessionChangeReason.SessionLock: 307 #if LOGEVENTS 308 EventLog.WriteEntry("SimpleService.OnSessionChange", 309 DateTime.Now.ToLongTimeString() + 310 " SessionLock"); 311 #endif 312 break; 313 314 case SessionChangeReason.SessionUnlock: 315 #if LOGEVENTS 316 EventLog.WriteEntry("SimpleService.OnSessionChange", 317 DateTime.Now.ToLongTimeString() + 318 " SessionUnlock"); 319 #endif 320 break; 321 322 default: 323 324 break; 325 } 326 } 327 // Define a simple method that runs as the worker thread for 328 // the service. 329 public void ServiceWorkerMethod() 330 { 331 #if LOGEVENTS 332 EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + 333 " - Starting the service worker thread."); 334 #endif 335 336 try 337 { 338 do 339 { 340 // Simulate 4 seconds of work. 341 Thread.Sleep(4000); 342 // Block if the service is paused or is shutting down. 343 pause.WaitOne(); 344 #if LOGEVENTS 345 EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + 346 " - heartbeat cycle."); 347 #endif 348 } 349 while (true); 350 } 351 catch (ThreadAbortException) 352 { 353 // Another thread has signalled that this worker 354 // thread must terminate. Typically, this occurs when 355 // the main service thread receives a service stop 356 // command. 357 358 // Write a trace line indicating that the worker thread 359 // is exiting. Notice that this simple thread does 360 // not have any local objects or data to clean up. 361 #if LOGEVENTS 362 EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + 363 " - Thread abort signaled."); 364 #endif 365 } 366 #if LOGEVENTS 367 368 EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + 369 " - Exiting the service worker thread."); 370 #endif 371 372 } 373 } 374 }