服務控制處理程式函式
每個服務都有一個控件處理程式,Handler 函式,當服務進程從服務控件程式收到控件要求時,由控制發送器叫用。 因此,此函式會在控件發送器的內容中執行。 如需範例,請參閱 撰寫控件處理程式函式。
服務會呼叫 RegisterServiceCtrlHandler 或 RegisterServiceCtrlHandlerEx 函式來註冊其服務控制處理程式函式。
叫用服務控件處理程式時,服務必須呼叫 SetServiceStatus 函式,只有在處理控制程式代碼導致服務狀態變更時,才會將其狀態回報給 SCM。 如果處理控制程式代碼未造成服務狀態變更,就不需要呼叫 setServiceStatus 。
服務控制程式可以使用 ControlService 函式來傳送控制要求。 所有服務都必須接受並處理 SERVICE_CONTROL_INTERROGATE 控件程式代碼。 您可以呼叫 setServiceStatus 來啟用或停用接受其他控制代碼。 若要接收 SERVICE_CONTROL_DEVICEEVENT 控件程序代碼,您必須呼叫 RegisterDeviceNotification 函式。 服務也可以處理額外的使用者定義控制碼。
如果服務接受 SERVICE_CONTROL_STOP 控件程式代碼,則必須在收到時停止,進入 SERVICE_STOP_PENDING 或 SERVICE_STOPPED 狀態。 在 SCM 傳送此控制程式代碼之後,它不會傳送其他控制程式代碼。
Windows XP: 如果服務傳回 NO_ERROR 並繼續執行,它會繼續接收控制碼。 從 Windows Server 2003 和 Windows XP 搭配 Service Pack 2 (SP2) 開始,此行為已變更。
控制程式處理程式必須在 30 秒內傳回,否則 SCM 會傳回錯誤。 如果服務在執行控制處理程式時必須執行冗長處理,它應該建立次要線程來執行冗長的處理,然後從控件處理程式傳回。 這可防止服務系結控制發送器。 例如,處理需要很長時間之服務的停止要求時,請建立另一個線程來處理停止進程。 控制項處理程式應該只要使用 SERVICE_STOP_PENDING 訊息呼叫 setServiceStatus,並傳回 。
當使用者關閉系統時,已呼叫 SetServiceStat us 的所有控件處理程式,SERVICE_ACCEPT_PRESHUTDOWN 控件程式代碼都會接收 SERVICE_CONTROL_PRESHUTDOWN 控件程式代碼。 服務控制管理員會等到服務停止或指定的逾時逾時值到期為止(這個值可以使用 ChangeServiceConfig2 函式來設定)。 此控制程式代碼應該只在特殊情況下使用,因為處理此通知的服務會封鎖系統關機,直到服務停止或逾時前時間間隔到期為止。
完成 preshutdown 通知之後,所有呼叫 setServiceStatus的控件處理程式,都會使用 SERVICE_ACCEPT_SHUTDOWN 控件程式代碼來接收 SERVICE_CONTROL_SHUTDOWN 控件程式代碼。 系統會依安裝服務資料庫中出現的順序通知它們。 根據預設,服務在系統關閉之前,大約需要 20 秒的時間來執行清除工作。 此時間到期之後,不論服務關機是否完成,系統關機都會繼續進行。 請注意,如果系統處於關機狀態(未重新啟動或關閉電源),服務會繼續執行。
如果服務需要更多時間來清除,它會傳送 STOP_PENDING 狀態消息,以及等候提示,因此服務控制器知道在向系統報告服務關機完成之前要等候的時間。 不過,若要防止服務停止關機,服務控制器等候的時間長度有限制。 如果服務正透過服務嵌入式管理單元關閉,則限製為125秒,或125,000毫秒。 如果作系統重新啟動,則會在下列登錄機碼的 WaitToKillServiceTimeout 值(以毫秒為單位)中指定時間限制:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
重要
服務不應該嘗試藉由修改此值來增加時間限制。 如果您需要手動設定 waitToKillServiceTimeout ,此值應該以毫秒為單位。
客戶需要快速關閉作系統。 例如,如果在 UPS 電源上執行的電腦無法在 UPS 用完電源之前完成關機,數據可能會遺失。 因此,服務應儘快完成其清除工作。 最好是定期儲存數據、追蹤儲存至磁碟的數據,以及只在關機時儲存未儲存的數據,以將未儲存的數據降到最低。 由於計算機正在關閉,因此請勿花時間釋放配置記憶體或其他系統資源。 如果您需要通知伺服器您正在結束,請將等候回復所花費的時間降到最低,因為網路問題可能會延遲服務的關機。
請注意,在服務關機期間,SCM 預設不會考慮相依性。 SCM 會列舉執行中的服務清單,並傳送 SERVICE_CONTROL_SHUTDOWN 命令。 因此,服務可能會失敗,因為它所依賴的另一個服務已經停止。
若要手動設定服務的關機順序,請建立包含服務名稱的多字元串登錄值,依應該關閉的順序,並將它指派給控制鍵的 PreshutdownOrder 值,如下所示:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PreshutdownOrder="Shutdown Order“
若要從您的應用程式設定相依服務的關機順序,請使用 SetProcessShutdownParameters 函式。 SCM 會使用此函式為其處理程式提供0x1E0優先順序。 SCM 會在呼叫其控件處理程式時傳送 SERVICE_CONTROL_SHUTDOWN 通知,並等候服務在從其控件處理程式傳回之前結束。
相關主題