說明
第一個程序是服務(wù),第二個程序控制服務(wù) 好像需要管理員權(quán)限,不然啟動失敗..
效果
服務(wù)程序 名字是 MiSaKaService.exe 在同一個文件夾中
源碼
#include
SERVICE_STATUS SplSrvServiceStatus;
SERVICE_STATUS_HANDLE SplSrvServiceStatusHandle;
VOID SvcDebugOut(LPSTR String, DWORD Status);
VOID WINAPI SplSrvServiceCtrlHandle(DWORD opcode);
VOID WINAPI SplSrvServiceStart(DWORD argc, LPTSTR *argv);
DWORD SplSrvServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError);
//啟動服務(wù)函數(shù)
VOID WINAPI SplSrvServiceStart(DWORD argc, LPTSTR *argv){
DWORD status;
DWORD specificError;
//填充結(jié)構(gòu)
SplSrvServiceStatus.dwServiceType = SERVICE_WIN32;
SplSrvServiceStatus.dwCurrentState = SERVICE_START_PENDING;//服務(wù)在運行
SplSrvServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
SplSrvServiceStatus.dwWin32ExitCode = 0;
SplSrvServiceStatus.dwServiceSpecificExitCode = 0;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
//注冊服務(wù)控制請求處理例程
SplSrvServiceStatusHandle = RegisterServiceCtrlHandler(
"MiSaKaService",//服務(wù)名
//SERVICE_WIN32_OWN_PROCESS在插件服務(wù)時使用了,所以本參數(shù)忽略
SplSrvServiceCtrlHandle//控制請求處理函數(shù)名
);
if (SplSrvServiceStatusHandle == (SERVICE_STATUS_HANDLE)0){
SvcDebugOut("注冊服務(wù)失敗: %d\n", GetLastError());
return;
}
//初始化,本示例未使用,函數(shù)為空
status = SplSrvServiceInitialization(argc, argv, &specificError);
//初始化失敗
if (status != NO_ERROR){
SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
SplSrvServiceStatus.dwWin32ExitCode = status;
SplSrvServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus);
return;
}
//初始化完成,設(shè)置運行狀態(tài)
SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){
status = GetLastError();
SvcDebugOut("服務(wù)初始化失敗: %d\n", status);
}
//自行修改,用戶完成服務(wù)的工作
SvcDebugOut("MiSaKa Servise 運行主線程\n", 0);
return;
}
//初始化工作,這里未進行任何工作,帶讀者修改
DWORD SplSrvServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError){
return 0;
}
//服務(wù)控制請求處理函數(shù),與ControlService函數(shù)配合
VOID WINAPI SplSrvServiceCtrlHandle(DWORD opcode){
DWORD status;
switch (opcode){
case SERVICE_CONTROL_PAUSE:
//完成相關(guān)功能
SplSrvServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
//完成相關(guān)功能
SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
//完成相關(guān)功能
SplSrvServiceStatus.dwWin32ExitCode = 0;
SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){
status = GetLastError();
SvcDebugOut("設(shè)置服務(wù)狀態(tài)錯誤 %ld\n", status);
}
SvcDebugOut("MiSaKa Service 服務(wù)結(jié)束,控制碼 %ld\n ", opcode);
break;
case SERVICE_CONTROL_INTERROGATE:
//完成相關(guān)功能 收到此請求發(fā)出響聲,演示服務(wù)控制請求的處理過程,可執(zhí)行修改
MessageBeep(MB_OK);
break;
default:
SvcDebugOut("未知的控制指令 %ld\n", opcode);
}
//當前狀態(tài)
if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){
status = GetLastError();
SvcDebugOut("設(shè)置服務(wù)狀態(tài)錯誤 %ld\n", status);
}
return;
}
//顯示信息給調(diào)試器
VOID SvcDebugOut(LPSTR String, DWORD Status){
CHAR Buffer[1024];
if (strlen(String)< 1000){
wsprintf(Buffer, String, Status);
OutputDebugString(Buffer);
}
}
//主函數(shù)
void main(){
//設(shè)置SERVICE_TABLE_ENTRY結(jié)構(gòu),以NULL結(jié)束
//作為StartServiceCtrlDispatcher函數(shù)的參數(shù)
SERVICE_TABLE_ENTRY DispatchTable[] = {
{ "MiSaKaService" ,(LPSERVICE_MAIN_FUNCTION)SplSrvServiceStart},
{NULL,NULL}
};
if (!StartServiceCtrlDispatcher(DispatchTable)){
SvcDebugOut("MiSaKa Service StartServiceCtrlDispatcher 錯誤 %d\n", GetLastError());
}
}
源碼
#include
#include
SC_HANDLE schService;//全局服務(wù)句柄
SC_HANDLE schSCManager;//SCM句柄
LPTSTR szServiceName = TEXT("MiSaKaService");//服務(wù)名
//創(chuàng)建服務(wù) SCM句柄 服務(wù)程序路徑 服務(wù)名
BOOL CreateSampleService(SC_HANDLE schSCManager, LPTSTR szPath, LPSTR szServiceName){
schService = CreateService(
schSCManager,//SCM句柄
szServiceName,//服務(wù)名
TEXT("御坂網(wǎng)絡(luò)服務(wù)"),//顯示的服務(wù)名
SERVICE_ALL_ACCESS,//存取權(quán)限
SERVICE_WIN32_OWN_PROCESS,//服務(wù)類別
SERVICE_DEMAND_START,//啟動類別
SERVICE_ERROR_NORMAL,//錯誤控制類別
szPath,//服務(wù)的可執(zhí)行文件路徑
NULL,//不屬于任何用戶組
NULL,//使用已存在的標簽
NULL,//獨立服務(wù)
NULL,//本地系統(tǒng)賬戶
NULL//密碼為空
);
if (schService == NULL){
printf("創(chuàng)建服務(wù)失敗 %d\n", GetLastError());
return FALSE;
} else{
printf("創(chuàng)建服務(wù)成功\n");
CloseServiceHandle(schService);
return TRUE;
}
}
//刪除服務(wù) 服務(wù)的名字
BOOL DeleteSampleService(LPTSTR szNameOfService){
schService = OpenService(
schSCManager,//SCM句柄
szNameOfService,//服務(wù)名
DELETE//可刪除
);
if (schService == NULL){
printf("打開服務(wù)失敗 %d\n", GetLastError());
return FALSE;
}
//刪除服務(wù)
if (!DeleteService(schService)){
printf("刪除服務(wù)失敗 %d\n", GetLastError());
return FALSE;
} else{
printf("刪除服務(wù)成功\n");
}
CloseServiceHandle(schService);
return TRUE;
}
//啟動服務(wù) SCM句柄 服務(wù)名
BOOL StartSampleService(SC_HANDLE schSCManager, LPTSTR szServiceName){
SC_HANDLE schService;
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwOldCheckPoint;
DWORD dwStartTickCount;
DWORD dwWaitTime;
DWORD dwBytesNeeded;
//打開服務(wù)
schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
if (schService == NULL){
return 0;
}
//啟動服務(wù)
if (!StartService(
schService,//服務(wù)的句柄
0,//參數(shù)個數(shù)為0
NULL//參數(shù)指針為NULL,沒有參數(shù)
)){
printf("啟動服務(wù)失敗 %u", GetLastError());
return 0;
} else{
printf("服務(wù)啟動成功...\n");
}
//驗證狀態(tài)
if (!QueryServiceStatusEx(
schService,//服務(wù)的句柄
SC_STATUS_PROCESS_INFO,//服務(wù)狀態(tài)信息
&ssStatus,//結(jié)構(gòu)體地址
sizeof(SERVICE_STATUS_PROCESS),//結(jié)構(gòu)體大小
&dwBytesNeeded//存儲狀態(tài)信息所用的字節(jié)數(shù)
)){
return 0;
}
//tick count & checkpoint
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
//查詢狀態(tài),確定PENDING狀態(tài)結(jié)束
while (ssStatus.dwCurrentState == SERVICE_START_PENDING){
//等待一段時間愛你
dwWaitTime = ssStatus.dwWaitHint / 10;
if (dwWaitTime< 1000){
dwWaitTime = 1000;
} else if (dwWaitTime>10000){
dwWaitTime = 10000;
}
Sleep(dwWaitTime);
//再次查詢
if (!QueryServiceStatusEx(
schService,//服務(wù)的句柄
SC_STATUS_PROCESS_INFO,//服務(wù)狀態(tài)信息
&ssStatus,//結(jié)構(gòu)體地址
sizeof(SERVICE_STATUS_PROCESS),//結(jié)構(gòu)體大小
&dwBytesNeeded//存儲狀態(tài)信息所用的字節(jié)數(shù)
)){
break;
}
if (ssStatus.dwCheckPoint>dwOldCheckPoint){
//進程創(chuàng)建中
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
} else{
if (GetTickCount() - dwStartTickCount>ssStatus.dwWaitHint){
//WaitHint 時間到
break;
}
}
}
//關(guān)閉句柄
CloseServiceHandle(schService);
//判斷是否創(chuàng)建成功 狀態(tài)由 PENDING 變?yōu)?RUNNING
if (ssStatus.dwCurrentState == SERVICE_RUNNING){
printf("創(chuàng)建服務(wù)成功\n");
return 1;
} else{
printf("創(chuàng)建服務(wù)失敗:\n");
printf("當前開始 %d\n", ssStatus.dwCurrentState);
printf("退出代碼 %d\n", ssStatus.dwWin32ExitCode);
printf("服務(wù)特定退出代碼 %d\n", ssStatus.dwServiceSpecificExitCode);
printf("檢查點 %d\n", ssStatus.dwCheckPoint);
printf("等待提示 %d\n", ssStatus.dwWaitHint);
return 0;
}
}
//向服務(wù)發(fā)送控制碼
BOOL ControlSampleService(DWORD fdwControl){
SERVICE_STATUS ssStatus;
DWORD fdwAccess;
DWORD dwStartTickCount;
DWORD dwWaitTime;
switch (fdwControl){
case SERVICE_CONTROL_STOP:
fdwAccess = SERVICE_STOP;
break;
case SERVICE_CONTROL_PAUSE:
caseSERVICE_CONTROL_CONTINUE:
fdwAccess = SERVICE_PAUSE_CONTINUE;
break;
case SERVICE_CONTROL_INTERROGATE:
fdwAccess = SERVICE_INTERROGATE;
break;
default:
fdwAccess = SERVICE_INTERROGATE;
}
//打開服務(wù)
schService = OpenService(
schSCManager,//SCM句柄
szServiceName,//服務(wù)名
fdwAccess//存取權(quán)限
);
if (schService == NULL){
printf("打開服務(wù)失敗 %d\n", GetLastError());
return FALSE;
}
//發(fā)送控制碼
if (!ControlService(
schService,//服務(wù)句柄
fdwControl,//控制碼
&ssStatus//狀態(tài)
)){
printf("控制服務(wù)失敗 %d\n", GetLastError());
return FALSE;
}
//顯示狀態(tài)
printf("御坂網(wǎng)絡(luò)服務(wù)狀態(tài):\n");
printf("服務(wù)類型 0x%x\n", ssStatus.dwServiceType);
printf("當前狀態(tài) 0x%x\n", ssStatus.dwCurrentState);
printf("接受控制 0x%x\n", ssStatus.dwControlsAccepted);
printf("退出代碼 %d\n", ssStatus.dwWin32ExitCode);
printf("服務(wù)特定退出代碼 %d\n", ssStatus.dwServiceSpecificExitCode);
printf("檢查點 %d\n", ssStatus.dwCheckPoint);
printf("等待提示 %d\n", ssStatus.dwWaitHint);
return TRUE;
}
//停止服務(wù) SCM句柄 服務(wù)名 是否結(jié)束依賴的服務(wù) 超時
DWORD StopService(SC_HANDLE hSCM, LPTSTR szServiceName, BOOL fStopDependencies, DWORD dwTimeout){
SERVICE_STATUS_PROCESS ssp;
SERVICE_STATUS ss;
DWORD dwStartTime = GetTickCount();
DWORD dwBytesNeeded;
//打開服務(wù)
SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);
//查詢狀態(tài),確定是否已經(jīng)停止
if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
return GetLastError();
}
if (ssp.dwControlsAccepted == SERVICE_STOPPED){
return ERROR_SUCCESS;
}
//如果是STOP_PENDING狀態(tài),則只需等待
while (ssp.dwCurrentState == SERVICE_STOP_PENDING){
Sleep(ssp.dwWaitHint);
//循環(huán)查詢,知道狀態(tài)改變
if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
return GetLastError();
}
if (ssp.dwCurrentState == SERVICE_STOPPED){
return ERROR_SUCCESS;
}
if (GetTickCount() - dwStartTime>dwTimeout){
return ERROR_TIMEOUT;
}
}
//先結(jié)束依賴服務(wù)
if (fStopDependencies){
DWORD i;
DWORD dwBytesNeeded;
DWORD dwCount;
LPENUM_SERVICE_STATUS lpDependencies = NULL;
ENUM_SERVICE_STATUS ess;
SC_HANDLE hDepService;
//使用0大小的buf,獲取buf的大小
//如果EnumDependentServices函數(shù)返回從,說明沒有依賴服務(wù)
if (!EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount)){
if (GetLastError() != ERROR_MORE_DATA){
return GetLastError();//意外的錯誤
}
lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);
if (!lpDependencies){
return GetLastError();
}
//獲得依賴服務(wù)
if (!EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount)){
return GetLastError();
}
for (i = 0; i< dwCount; i++){
ess = *(lpDependencies + i);
//打開服務(wù)
hDepService = OpenService(hSCM, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
if (!hDepService){
return GetLastError();
}
//結(jié)束服務(wù)
if (!ControlService(hDepService, SERVICE_CONTROL_STOP, &ss)){
return GetLastError();
}
//等待服務(wù)結(jié)束
while (ss.dwCurrentState != SERVICE_STOPPED){
Sleep(ss.dwWaitHint);
if (!QueryServiceStatusEx(hDepService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
if (ss.dwCurrentState == SERVICE_STOPPED){
break;
}
if (GetTickCount() - dwStartTime>dwTimeout){
return ERROR_TIMEOUT;
}
}
}
//關(guān)閉服務(wù)
CloseServiceHandle(hDepService);
}
//是否內(nèi)存
HeapFree(GetProcessHeap(), 0, lpDependencies);
}
}
//所有依賴服務(wù)以及結(jié)束,技術(shù)指定服務(wù)
if (!ControlService(hService, SERVICE_CONTROL_STOP, &ss)){
return GetLastError();
}
while (ss.dwCurrentState != SERVICE_STOPPED){
Sleep(ss.dwWaitHint);
if(!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
return GetLastError();
}
if (ss.dwCurrentState == SERVICE_STOPPED){
break;
}
if (GetTickCount()-dwStartTime>dwTimeout){
return ERROR_TIMEOUT;
}
}
return ERROR_SUCCESS;
}
int main(int argc, TCHAR *argv[]){
TCHAR szBinFilePath[MAX_PATH];
PTCHAR pTemp;
DWORD dwStopError;
//構(gòu)造服務(wù)可執(zhí)行程序的路徑
GetModuleFileName(NULL, szBinFilePath, MAX_PATH);
pTemp = szBinFilePath + lstrlen(szBinFilePath);
while (*--pTemp != '\\');
lstrcpy(pTemp, TEXT("\\MiSaKaService.exe"));
//打開SCM
schSCManager = OpenSCManager(
NULL,//本機
NULL,//ServicesActive數(shù)據(jù)庫
SC_MANAGER_ALL_ACCESS//完全存取權(quán)限
);
if (schSCManager == NULL){
printf("打開SCM失敗 %d\n", GetLastError());
}
//創(chuàng)建服務(wù)
CreateSampleService(schSCManager, szBinFilePath, szServiceName);
//啟動服務(wù)
StartSampleService(schSCManager, szServiceName);
//發(fā)送請求控制
ControlSampleService(SERVICE_CONTROL_INTERROGATE);
ControlSampleService(SERVICE_CONTROL_CONTINUE);
//停止服務(wù)
dwStopError = StopService(schSCManager, szServiceName, TRUE, 1000);
if (dwStopError == ERROR_SUCCESS){
printf("服務(wù)成功停止\n");
} else{
printf("服務(wù)停止失敗\n");
}
//刪除服務(wù)
DeleteSampleService(szServiceName);
CloseServiceHandle(schSCManager);
getchar();
return 0;
}