LPHANDLER_FUNCTION_EX回调函数 (winsvc.h)

RegisterServiceCtrlHandlerEx 函数一起使用的应用程序定义的回调函数。 服务程序可以使用它作为特定服务的控制处理程序函数。

LPHANDLER_FUNCTION_EX类型定义指向此函数的指针。 HandlerEx 是应用程序定义名称的占位符。

此函数取代了与 RegisterServiceCtrlHandler 函数一起使用的 Handler 控件处理程序函数。 服务可以使用任一控件处理程序,但新的控件处理程序支持用户定义的上下文数据和附加的扩展控制代码。

语法

LPHANDLER_FUNCTION_EX LphandlerFunctionEx;

DWORD LphandlerFunctionEx(
  [in] DWORD dwControl,
  [in] DWORD dwEventType,
  [in] LPVOID lpEventData,
  [in] LPVOID lpContext
)
{...}

参数

[in] dwControl

控件代码。 此参数的取值可为下列值之一:

控制代码 含义
SERVICE_CONTROL_CONTINUE
0x00000003
通知暂停的服务应恢复。
SERVICE_CONTROL_INTERROGATE
0x00000004
通知服务将其当前状态信息报告给服务控制管理器。

处理程序应仅返回 NO_ERROR;SCM 知道服务的当前状态。

SERVICE_CONTROL_NETBINDADD
0x00000007
通知网络服务有用于绑定的新组件。 服务应绑定到新组件。

应用程序应改用即插即用功能。

SERVICE_CONTROL_NETBINDDISABLE
0x0000000A
通知网络服务其其中一个绑定已被禁用。 服务应重新读取其绑定信息并删除绑定。

应用程序应改用即插即用功能。

SERVICE_CONTROL_NETBINDENABLE
0x00000009
通知网络服务已启用禁用的绑定。 服务应重新读取其绑定信息并添加新绑定。

应用程序应改用即插即用功能。

SERVICE_CONTROL_NETBINDREMOVE
0x00000008
通知网络服务已删除用于绑定的组件。 服务应重新读取其绑定信息,并从已删除的组件取消绑定。

应用程序应改用即插即用功能。

SERVICE_CONTROL_PARAMCHANGE
0x00000006
通知服务特定于服务的启动参数已更改。 服务应重新读取其启动参数。
SERVICE_CONTROL_PAUSE
0x00000002
通知服务它应暂停。
SERVICE_CONTROL_PRESHUTDOWN
0x0000000F
通知服务系统将关闭。 在系统关闭时,需要额外时间来执行超出严格时间限制的清理任务的服务可以使用此通知。 服务控制管理器将此通知发送给已注册此通知的应用程序,然后再将 SERVICE_CONTROL_SHUTDOWN 通知发送到已注册该通知的应用程序。

处理此通知的服务会阻止系统关闭,直到服务停止或通过 SERVICE_PRESHUTDOWN_INFO 指定的预超时间隔过期。 由于这会影响用户体验,因此只有在下次系统启动时绝对有必要避免数据丢失或长时间恢复时,服务才应使用此功能。

Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONTROL_SHUTDOWN
0x00000005
通知服务系统正在关闭,以便该服务可以执行清理任务。 请注意,注册 SERVICE_CONTROL_PRESHUTDOWN 通知的服务无法收到此通知,因为它们已停止。

如果服务接受此控制代码,则它必须在执行清理任务后停止并返回 NO_ERROR。 SCM 发送此控制代码后,不会向服务发送其他控制代码。

有关详细信息,请参阅本主题的“备注”部分。

SERVICE_CONTROL_STOP
0x00000001
通知服务它应停止。

如果服务接受此控制代码,则必须在收到后停止并返回 NO_ERROR。 SCM 发送此控制代码后,不会向服务发送其他控制代码。 Windowsxp: 如果服务返回 NO_ERROR 并继续运行,它将继续接收控制代码。 此行为从 Windows Server 2003 和 Windows XP SP2 开始发生了更改。

 

此参数也可以是以下扩展控制代码之一。 请注意, 处理程序 函数不支持这些控制代码。

控制代码 含义
SERVICE_CONTROL_DEVICEEVENT
0x0000000B
通知服务设备事件。 (服务必须已注册才能使用 RegisterDeviceNotification 函数接收这些通知。) dwEventTypelpEventData 参数包含其他信息。
SERVICE_CONTROL_HARDWAREPROFILECHANGE
0x0000000C
通知服务计算机的硬件配置文件已更改。 dwEventType 参数包含其他信息。
SERVICE_CONTROL_POWEREVENT
0x0000000D
通知服务系统电源事件。 dwEventType 参数包含其他信息。 如果 dwEventType是PBT_POWERSETTINGCHANGE则 lpEventData 参数还包含其他信息。
SERVICE_CONTROL_SESSIONCHANGE
0x0000000E
通知服务会话更改事件。 请注意,仅当服务在登录尝试之前已完全加载时,才会收到用户登录的通知。 dwEventTypelpEventData 参数包含其他信息。
SERVICE_CONTROL_TIMECHANGE
0x00000010
通知服务系统时间已更改。 lpEventData 参数包含其他信息。 不使用 dwEventType 参数。

Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP: 不支持此控制代码。

SERVICE_CONTROL_TRIGGEREVENT
0x00000020
通知已注册服务 触发器事件的服务 该事件已发生。

Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP: 不支持此控制代码。

SERVICE_CONTROL_USERMODEREBOOT
0x00000040
通知服务用户已启动重新启动。

Windows Server 2008 R2、Windows 7、Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP: 不支持此控制代码。

 

此参数也可以是用户定义的控件代码,如下表所述。

控制代码 含义
范围为 128 到 255。
服务定义与控制代码关联的操作。

[in] dwEventType

已发生的事件的类型。 如果 dwControl是SERVICE_CONTROL_DEVICEEVENTSERVICE_CONTROL_HARDWAREPROFILECHANGESERVICE_CONTROL_POWEREVENTSERVICE_CONTROL_SESSIONCHANGE,则使用此参数。 否则为零。

如果 dwControlSERVICE_CONTROL_DEVICEEVENT,则此参数可以是以下值之一:

如果 dwControlSERVICE_CONTROL_HARDWAREPROFILECHANGE,则此参数可以是以下值之一: 如果 dwControlSERVICE_CONTROL_POWEREVENT,此参数可以是WM_POWERBROADCAST消息的 wParam 参数中指定的值之一。

如果 dwControlSERVICE_CONTROL_SESSIONCHANGE,则此参数可以是WM_WTSSESSION_CHANGE消息的 wParam 参数中指定的值之一。

[in] lpEventData

其他设备信息(如果需要)。 此数据的格式取决于 dwControldwEventType 参数的值。

如果 dwControlSERVICE_CONTROL_DEVICEEVENT,则此数据对应于应用程序作为WM_DEVICECHANGE消息的一部分接收lParam 参数。

如果 dwControlSERVICE_CONTROL_POWEREVENTdwEventType PBT_POWERSETTINGCHANGE,则此数据是指向 POWERBROADCAST_SETTING 结构的指针。

如果SERVICE_CONTROL_SESSIONCHANGE dwControl,则此参数是指向WTSSESSION_NOTIFICATION结构的指针。

如果SERVICE_CONTROL_TIMECHANGE dwControl,则此数据是指向SERVICE_TIMECHANGE_INFO结构的指针。

[in] lpContext

RegisterServiceCtrlHandlerEx 传递的用户定义数据。 当多个服务共享一个进程时, lpContext 参数可以帮助标识该服务。

返回值

此函数的返回值取决于收到的控制代码。

以下列表标识此返回值的规则:

  • 通常,如果服务不处理控件,则返回 ERROR_CALL_NOT_IMPLEMENTED。 但是,即使服务不处理 SERVICE_CONTROL_INTERROGATE ,服务也应返回 NO_ERROR
  • 如果服务处理 SERVICE_CONTROL_STOPSERVICE_CONTROL_SHUTDOWN请返回NO_ERROR
  • 如果服务处理 SERVICE_CONTROL_DEVICEEVENT,请返回 NO_ERROR 以授予请求,并返回错误代码以拒绝请求。
  • 如果服务处理 SERVICE_CONTROL_HARDWAREPROFILECHANGE,请返回 NO_ERROR 以授予请求,并返回错误代码以拒绝请求。
  • 如果服务处理 SERVICE_CONTROL_POWEREVENT,请返回 NO_ERROR 以授予请求,并返回错误代码以拒绝请求。
  • 对于服务处理的其他所有控制代码,返回 NO_ERROR

注解

服务启动时,其 ServiceMain 函数应立即调用 RegisterServiceCtrlHandlerEx 函数,以指定 HandlerEx 函数来处理控制请求。 若要指定要接受的控制代码,请使用 SetServiceStatusRegisterDeviceNotification 函数。

服务main线程中的控制调度程序在收到来自服务控制管理器的控制请求时,都会调用指定服务的控件处理程序函数。 处理控制请求后,如果服务状态更改为向服务控制管理器报告其新状态,控件处理程序必须调用 SetServiceStatus

控制处理程序函数旨在接收通知并立即返回。 回调函数应保存其参数并创建其他线程以执行其他工作。 (应用程序必须确保此类线程在停止 service 之前已退出。) 具体而言,控制处理程序应避免可能阻止的操作,例如获取锁,因为这可能会导致死锁或导致系统停止响应。

当服务控制管理器向服务发送控制代码时,它会等待处理程序函数返回,然后再向其他服务发送其他控制代码。 控件处理程序应尽快返回;如果它在 30 秒内未返回,则 SCM 将返回错误。 如果服务在执行控件处理程序时必须执行冗长处理,则它应创建一个辅助线程来执行冗长的处理,然后从控件处理程序返回。 这可以防止服务将控制调度程序绑起来,并阻止其他服务接收控制代码。

SERVICE_CONTROL_SHUTDOWN控制代码只应由在关闭期间必须绝对清理的服务进行处理,因为服务关闭的时间有限, (大约 20 秒) 可用。 此时间到期后,无论服务关闭是否完成,系统关闭都会继续。 请注意,如果系统保持关闭状态 (未重启或关闭) ,则服务将继续运行。 如果服务注册接受 SERVICE_CONTROL_SHUTDOWN,则必须处理控制代码并返回 NO_ERROR。 返回此控制代码的错误且未及时停止可能会增加关闭系统所需的时间,因为系统必须等待服务关闭所允许的全部时间,然后系统才能继续关闭。

如果服务需要更多时间进行清理,它应发送 STOP_PENDING 状态消息以及等待提示,以便服务控制器知道在向系统报告服务关闭已完成之前等待的时间。 但是,为了防止服务停止关闭,服务控制器的等待时间有限制。 如果通过服务管理单元关闭服务,则限制为 125 秒。 如果操作系统正在重新启动,则会在以下注册表项的 WaitToKillServiceTimeout 值中指定时间限制:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

请务必尽快处理即插即用设备事件;否则,系统可能会变得无响应。 如果事件处理程序要执行可能会阻止执行 ((如 I/O) )的操作,则最好启动另一个线程以异步方式执行该操作。

服务还可以使用 SetConsoleCtrlHandler 函数接收关闭通知。 当正在运行的应用程序关闭时(在关闭服务之前发生)时,会收到此通知。

要求

要求
最低受支持的客户端 Windows XP [仅限桌面应用]
最低受支持的服务器 Windows Server 2003 [仅限桌面应用]
目标平台 Windows
标头 winsvc.h (包括 Windows.h)

另请参阅

POWERBROADCAST_SETTING

RegisterDeviceNotification

RegisterServiceCtrlHandlerEx

服务控制处理程序函数

服务函数

ServiceMain

SetServiceStatus

WM_DEVICECHANGE

WM_POWERBROADCAST

WM_WTSSESSION_CHANGE

WTSSESSION_NOTIFICATION