ntservice.rar:NTService 服務範例ntservicecpl.rar:NTServCpl 控制台程式ntservicectrl.rar:NTServCtrl 服務監控程式服務為 OS 啟動即執行的背景程式,無需使用者登入。適用目錄複寫、行程監控、網路服務 (HTTP 等)。
以單一 C++ 類別 CNTService 封裝服務核心功能,衍生類別僅需覆寫少數虛擬函數。內建安裝/移除/版本報告於服務 EXE 本體,單一檔案部署。
-v:報告服務名稱與版本-i:安裝服務-u:移除服務服務無 UI,必須寫入系統/應用程式事件日誌。使用 ReportEvent API,需:
.mc 訊息定義檔 (含 MessageId、SymbolicName、語言、文字)mc.exe 編譯產生 .h、.rc、.bin.rc 包含產生的 .rc 與 windows.h.h 使用符號名稱// 訊息範例
MessageId=100
SymbolicName=EVMSG_INSTALLED
Language=English
The %1 service was installed.
.
寫入日誌:
void CNTService::LogEvent(WORD wType, DWORD dwID, const char* pszS1, ...)
{
// 組裝參數陣列,呼叫 RegisterEventSource + ReportEvent
}
三個關鍵函數:
main:進入點,解析參數、安裝/移除/啟動ServiceMain:真正服務進入點,向 SCM 註冊Handler:處理 SCM 控制訊息因 SCM 直接呼叫 ServiceMain/Handler,無法傳遞 this 指標,採用靜態成員變數 m_pThis 儲存單一服務物件指標 (限制每程式單一服務物件)。
封裝理念:「我要這物件做什麼」而非「Windows API 做什麼」。提供:
Run():必須,服務主體工作迴圈OnInit():初始化 (讀登錄檔等)OnUserControl(DWORD):處理 ControlService 使用者自訂訊息 (128-255)OnStop()/OnShutdown():清理作業class CMyService : public CNTService
{
public:
CMyService();
virtual BOOL OnInit();
virtual void Run();
virtual BOOL OnUserControl(DWORD dwOpcode);
void SaveStatus();
int m_iStartParam, m_iIncParam, m_iState;
};
int main(int argc, char* argv[])
{
CMyService MyService;
if (!MyService.ParseStandardArgs(argc, argv))
{
// DebugBreak(); // 除錯用
MyService.StartService();
}
return MyService.m_Status.dwWin32ExitCode;
}
BOOL CMyService::OnInit()
{
HKEY hkey;
char szKey[1024];
strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\");
strcat(szKey, m_szServiceName);
strcat(szKey, "\\Parameters");
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
{
DWORD dwType, dwSize = sizeof(m_iStartParam);
RegQueryValueEx(hkey, "Start", NULL, &dwType, (BYTE*)&m_iStartParam, &dwSize);
dwSize = sizeof(m_iIncParam);
RegQueryValueEx(hkey, "Inc", NULL, &dwType, (BYTE*)&m_iIncParam, &dwSize);
RegCloseKey(hkey);
}
m_iState = m_iStartParam;
return TRUE;
}
void CMyService::Run()
{
while (m_bIsRunning)
{
DebugMsg("My service is sleeping (%lu)...", m_iState);
Sleep(1000);
m_iState += m_iIncParam;
}
}
BOOL CMyService::OnUserControl(DWORD dwOpcode)
{
if (dwOpcode == SERVICE_CONTROL_USER + 0)
{
SaveStatus(); // 寫入登錄檔供其他程式讀取
return TRUE;
}
return FALSE;
}
DebugBreak() 啟動系統除錯器CNTService::DebugMsg 輸出追蹤訊息WinDbg (Platform SDK) 或使用 Visual Studio 除錯器CNTService 類別大幅簡化 Win32 服務開發,衍生類別專注業務邏輯,適合快速建置背景服務。