| API | 用途 |
OpenSCManager | 打開服務控制管理器數據庫 |
CreateService | 創建新服務 |
OpenService | 打開現有服務獲取句柄 |
ControlService | 發送控制碼(停止、暫停等) |
DeleteService | 刪除服務 |
RegisterServiceCtrlHandler | 註冊服務控制處理函數 |
SetServiceStatus | 報告服務狀態給 SCM |
StartServiceCtrlDispatcher | 連接服務主線程與 SCM |
實現步驟詳解
1. 項目創建與全局定義
- 創建 Win32 Application(無界面),命名
ServiceTest
- 定義全局變量:服務名、狀態結構、狀態句柄、線程 ID
- 聲明核心函數:
Init、Install、Uninstall、ServiceMain、ServiceCtrl
2. 初始化函數 Init()
hServiceStatus = NULL;
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
status.dwCurrentState = SERVICE_STOPPED;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP; // 關鍵:接受停止控制
status.dwWin32ExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
3. 安裝服務 Install()
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SC_HANDLE hService = CreateService(
hSCM, szServiceName, szServiceName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
szFilePath, NULL, NULL, L"", NULL, NULL);
// 關鍵參數:SERVICE_DEMAND_START = 手動啟動
// 若需自動啟動改為 SERVICE_AUTO_START
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
4. 卸載服務 Uninstall()
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);
ControlService(hService, SERVICE_CONTROL_STOP, &status); // 先停止
DeleteService(hService); // 再刪除
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
5. 服務主線程 ServiceMain()
status.dwCurrentState = SERVICE_START_PENDING;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceCtrl);
if (!hServiceStatus) { LogEvent(L"Handler not installed"); return; }
SetServiceStatus(hServiceStatus, &status);
// 初始化完成,進入運行狀態
status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hServiceStatus, &status);
// === 核心業務邏輯放這裡 ===
int i = 0;
while (i < 10) { Sleep(1000); i++; } // 模擬工作 10 秒
// ==========================
status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hServiceStatus, &status);
LogEvent(L"Service stopped");
6. 控制處理函數 ServiceCtrl()
void WINAPI ServiceCtrl(DWORD dwOpcode) {
switch (dwOpcode) {
case SERVICE_CONTROL_STOP:
status.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(hServiceStatus, &status);
// 執行清理工作...
status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hServiceStatus, &status);
break;
case SERVICE_CONTROL_PAUSE: /* ... */ break;
case SERVICE_CONTROL_CONTINUE: /* ... */ break;
case SERVICE_CONTROL_INTERROGATE: /* ... */ break;
}
}
7. 入口點 WinMain 命令行分發
Init();
SERVICE_TABLE_ENTRY st[] = {
{ szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
if (stricmp(lpCmdLine, "/install") == 0) Install();
else if (stricmp(lpCmdLine, "/uninstall") == 0) Uninstall();
else {
if (!StartServiceCtrlDispatcher(st))
LogEvent(L"Register Service Main Function Error!");
}
用法:
ServiceTest.exe /install 安裝服務
ServiceTest.exe /uninstall 卸載服務
ServiceTest.exe (由 SCM 啟動)運行服務
關鍵注意事項
- dwControlsAccepted 必須設置:否則 SCM 不會發送控制碼,服務無法被停止/暫停
- 狀態報告及時:每次狀態變化必須調用
SetServiceStatus
- 服務類型選擇:
SERVICE_WIN32_OWN_PROCESS 獨立進程;SERVICE_WIN32_SHARE_PROCESS 共享進程
- 錯誤處理:所有 API 返回值必須檢查,失敗時記錄日誌
- 調試技巧:開發階段可作為控制台程序運行,通過條件編譯切換
總結
Windows 服務開發核心在於:理解 SCM 架構、正確實現狀態機、註冊控制處理器、業務邏輯與服務框架分離。掌握本文框架,即可快速構建穩健的後台服務程序。
- 上一篇文章: VC 中鼠標檢測與自定義光標實現指南
- 下一篇文章: VC++實現光驅彈出與插入狀態的自動監測
Copyright ©
程式碼之家 All Rights Reserved