在開發 Windows 系統服務時,若將 dwControlsAccepted 設為 SERVICE_ACCEPT_SHUTDOWN 而不接受 SERVICE_ACCEPT_STOP,會導致服務控制管理器 (SCM) 無法透過 ControlService 發送 SERVICE_CONTROL_STOP 來停止服務。此時需要替代機制來讓服務優雅退出。
建立一個全域的 Event 物件,在服務的主迴圈中定期檢查該 Event 的狀態。當需要停止服務時,由外部程式(如管理工具或另一個服務)呼叫 SetEvent 觸發該事件,服務偵測到事件被觸發後即可執行清理工作並退出。
CreateEvent 建立一個手動重置、初始狀態為非觸發的 Event。WaitForSingleObject 搭配短暫逾時(例如 1 秒)來輪詢 Event 狀態,避免阻塞。WaitForSingleObject 返回 WAIT_OBJECT_0,表示 Event 被觸發,跳出迴圈進入停止流程。OpenEvent 取得 Event 句柄,再呼叫 SetEvent 通知服務停止。// 服務內部
HANDLE g_hStopEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("Global\\MyServiceStopEvent"));
// 工作迴圈
while (true) {
DWORD dwWait = WaitForSingleObject(g_hStopEvent, 1000); // 1 秒輪詢一次
if (dwWait == WAIT_OBJECT_0) {
// 收到停止信號
break;
}
// 執行定期工作...
}
// 外部停止工具
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("Global\\MyServiceStopEvent"));
if (hEvent) {
SetEvent(hEvent);
CloseHandle(hEvent);
}
此方案為 Windows 服務開發中常見的替代停止機制,尤其在無法接受標準 STOP 命令時相當實用。