首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Windows 服務程式拒絕 STOP 命令時的替代停止方案

     編輯:程式設計綜合問答

問題背景

在開發 Windows 系統服務時,若將 dwControlsAccepted 設為 SERVICE_ACCEPT_SHUTDOWN 而不接受 SERVICE_ACCEPT_STOP,會導致服務控制管理器 (SCM) 無法透過 ControlService 發送 SERVICE_CONTROL_STOP 來停止服務。此時需要替代機制來讓服務優雅退出。

解決方案:使用全域 Event 物件

建立一個全域的 Event 物件,在服務的主迴圈中定期檢查該 Event 的狀態。當需要停止服務時,由外部程式(如管理工具或另一個服務)呼叫 SetEvent 觸發該事件,服務偵測到事件被觸發後即可執行清理工作並退出。

實作步驟

  1. 在服務啟動時呼叫 CreateEvent 建立一個手動重置、初始狀態為非觸發的 Event。
  2. 在服務的工作執行緒迴圈中,使用 WaitForSingleObject 搭配短暫逾時(例如 1 秒)來輪詢 Event 狀態,避免阻塞。
  3. 若 WaitForSingleObject 返回 WAIT_OBJECT_0,表示 Event 被觸發,跳出迴圈進入停止流程。
  4. 提供一個獨立的控制程式或命令列工具,呼叫 OpenEvent 取得 Event 句柄,再呼叫 SetEvent 通知服務停止。

程式碼片段示意 (C++)

// 服務內部
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);
}

優缺點分析

  • 優點:不依賴 SCM 的停止命令,適用於特殊安全需求或嵌入式環境;實作簡單,跨進程同步可靠。
  • 缺點:需自行管理 Event 的命名與權限,避免衝突;外部停止工具需具備足夠權限開啟 Event。

此方案為 Windows 服務開發中常見的替代停止機制,尤其在無法接受標準 STOP 命令時相當實用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved