什麼是 Windows 服務?
**服務** 是一種特殊的 Win32 可執行程式,具備以下核心特徵:
- 無用戶界面 (Headless):不依賴桌面交互,通常以主控台程式 (`main()` 入口) 形式編寫,不顯示視窗、訊息框。
- 後台長駐:可在**無用戶登入**時隨系統啟動 (Auto-start),或由 SCM 按需啟動。
- 特權運行:通常在 `LocalSystem`、`NetworkService`、`LocalService` 或自定義服務帳戶下運行,擁有高於普通用戶的系統權限。
- 生命週期受 SCM 管控:啟動、停止、暫停、恢復均透過服務控制管理器 (SCM, `services.exe`) 統一調度。
- 遠程可管理性:支援透過網路 (RPC/WinRM/WMI) 從其他電腦管理 (MMC 擴充單元、PowerShell、SC 命令)。
為什麼選擇服務架構?
| 場景 | 傳統 GUI 程式 | Windows 服務 |
| 伺服器軟體 (Web/DB/FTP/郵件) | 需用戶登入、佔用桌面、易誤關閉 | 開機自啟、無人值守、高可用 |
| 系統監控/備份/同步代理 | 用戶登出即停止 | 持續後台運行 |
| 硬體驅動/過濾/安全代理 | 無法載入內核/過濾器 | 早期啟動、高權限訪問硬體 |
| 企業級部署 (群策略/MDM) | 難以統一配置、狀態查詢 | 標準化管理介面 (WMI/SCM) |
服務類型分類
- Win32 Own Process (SERVICE_WIN32_OWN_PROCESS):獨立進程 (`svc.exe`),最常見,本系列重點。
- Win32 Share Process (SERVICE_WIN32_SHARE_PROCESS):共享進程 (`svchost.exe` 載入 DLL),如系統服務。需導出 `ServiceMain`,DLL 入口不同。
- Kernel Driver (SERVICE_KERNEL_DRIVER / FILE_SYSTEM_DRIVER):內核模式驅動,非用戶模式服務,開發門檻極高。
- Interactive Service (已棄用/受限):早期允許與桌面交互 (SERVICE_INTERACTIVE_PROCESS),Vista+ Session 0 隔離機制嚴格禁止,不可用於新開發。
核心開發知識體系
編寫功能完備、健壯的服務需掌握:
- 進程/線程同步:事件、互斥體、信號燈、IOCP、SRW Lock、條件變量。
- 異常處理 (SEH/VEH):防止未捕獲異常導致服務崩潰,需全局異常過濾器 + 迷你傾印。
- 虛擬記憶體/記憶體映射文件:高性能數據交換、共享記憶體 IPC。
- 設備 I/O 控制:與內核驅動通訊 (`DeviceIoControl`)。
- Unicode/字符集:服務通常在無用戶語系環境下運行,必須顯式指定字符集,避免亂碼。
- 安全描述符/ACL/Token/Impersonation:資源訪問控制、客戶端身份模擬。
- 事件日誌 (Event Log):服務無 UI,日誌是唯一可見性來源 (`ReportEvent`)。
- WMI/Performance Counters:暴露管理數據、健康指標。
遠程管理:跨機器服務控制
Windows 內建工具支援遠程管理:
- MMC (mmc.exe) + 服務 擴充單元 (services.msc) → 右鍵「連線到另一台電腦」。
- SC 命令:`sc \\\\RemotePC start MyService`
- PowerShell:`Get-Service -ComputerName Server01 -Name MyService | Restart-Service`
- WMI/CIM:`Get-CimInstance -ClassName Win32_Service -ComputerName Server01`
- WinRM/WS-Man:`Enter-PSSession -ComputerName Server01` 後本地管理。
**前提**:目標機器啟用 `Remote Registry` 服務、防火牆開放 RPC/WMI/WinRM 埠、調用者具備目標機器管理員權限 (或委派權限)。
本系列規劃
- (一) 核心概念與架構 (本文)
- (二) ServiceMain 與 StartServiceCtrlDispatcher 協作機制
- (三) 控制處理器 (CtrlHandler) 完整指南
- (四) 進階問題:線程通信、狀態回報策略、錯誤處理、安裝部署
給新手的建議
- **先寫主控台程式驗證核心邏輯**,再包裝為服務框架。
- **使用成熟框架/庫**:C++ 可用
Windows Service Template (VS)、Boost.Application、POCO::Util::ServerApplication;C# 直接用 BackgroundService / HostBuilder;Go 用 github.com/kardianos/service;Rust 用 windows-service。
- **從安裝腳本開始**:用 `sc create` / `New-Service` / WiX/NSIS 安裝包註冊服務,而非手動 `reg add`。
- **日誌先行**:引入 `spdlog`/`log4cplus`/`Serilog`,輸出至文件 + 事件日誌,無日誌無真相。
- **測試停電/關機/更新重啟**:模擬 `SERVICE_CONTROL_SHUTDOWN`、`SERVICE_CONTROL_PRESHUTDOWN` (Vista+),驗證數據零丟失。