服務控制處理函式
每個服務都有控制項處理常式 Handler 函式,當服務進程從服務控制程式收到控制項要求時,控制發送器會叫用此函式。 因此,此函式會在控制項發送器的內容中執行。 如需範例,請參閱 撰寫控制項處理常式函式。
服務會呼叫 RegisterServiceCtrlHandler 或 RegisterServiceCtrlHandlerEx 函式來註冊其服務控制處理常式函式。
叫用服務控制處理常式時,服務必須呼叫 SetServiceStatus 函式,只有在處理控制程式代碼導致服務狀態變更時,才會將其狀態報表給 SCM。 如果處理控制程式代碼不會導致服務狀態變更,就不需要呼叫 SetServiceStatus。
服務控制程式可以使用 ControlService 函式來傳送控制要求。 所有服務都必須接受並處理 SERVICE_CONTROL_INTERROGATE 控制項程式碼。 您可以呼叫 SetServiceStatus來啟用或停用接受其他控制程式代碼。 若要接收 SERVICE_CONTROL_DEVICEEVENT 控制項程式碼,您必須呼叫 RegisterDeviceNotification 函式 。 服務也可以處理其他使用者定義的控制程式代碼。
如果服務接受 SERVICE_CONTROL_STOP 控制程式代碼,則必須在收到時停止,並移至 SERVICE_STOP_PENDING 或 SERVICE_STOPPED 狀態。 在 SCM 傳送此控制程式代碼之後,它不會傳送其他控制代碼。
Windowsxp: 如果服務傳回 NO_ERROR 並繼續執行,則會繼續接收控制碼。 此行為從 Windows Server 2003 和 Service Pack 2 (SP2) 開始變更。
控制處理常式必須在 30 秒內傳回,否則 SCM 會傳回錯誤。 如果服務在執行控制處理常式時必須執行冗長的處理,它應該建立次要執行緒來執行冗長的處理,然後從控制項處理常式傳回。 這可防止服務將控制發送器系結在一起。 例如,處理需要很長時間之服務的停止要求時,請建立另一個執行緒來處理停止進程。 控制項處理常式應該只會使用SERVICE_STOP_PENDING訊息呼叫SetServiceStatus並傳回。
當使用者關閉系統時,呼叫 SetServiceStatus 且 具有SERVICE_ACCEPT_PRESHUTDOWN 控制項程式碼的所有控制項處理常式都會收到 SERVICE_CONTROL_PRESHUTDOWN 控制項程式碼。 服務控制管理員會等到服務停止或指定的預先逾時逾時值到期, (此值可以使用 ChangeServiceConfig2 函式設定) 。 此控制程式代碼應該只在特殊情況下使用,因為處理此通知的服務會封鎖系統關機,直到服務停止或前置逾時時間間隔到期為止。
完成前置通知之後,所有呼叫 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 通知,並等候服務在從其控制項處理常式傳回之前結束。
相關主題