一個服務程序

說明

第一個程序是服務,第二個程序控制服務 好像需要管理員權限,不然啟動失敗..

效果

服務程序 名字是 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);

//啟動服務函數

VOID WINAPI SplSrvServiceStart(DWORD argc, LPTSTR *argv){

DWORD status;

DWORD specificError;

//填充結構

SplSrvServiceStatus.dwServiceType = SERVICE_WIN32;

SplSrvServiceStatus.dwCurrentState = SERVICE_START_PENDING;//服務在運行

SplSrvServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;

SplSrvServiceStatus.dwWin32ExitCode = 0;

SplSrvServiceStatus.dwServiceSpecificExitCode = 0;

SplSrvServiceStatus.dwCheckPoint = 0;

SplSrvServiceStatus.dwWaitHint = 0;

//注冊服務控制請求處理例程

SplSrvServiceStatusHandle = RegisterServiceCtrlHandler(

"MiSaKaService",//服務名

//SERVICE_WIN32_OWN_PROCESS在插件服務時使用了,所以本參數忽略

SplSrvServiceCtrlHandle//控制請求處理函數名

);

if (SplSrvServiceStatusHandle == (SERVICE_STATUS_HANDLE)0){

SvcDebugOut("注冊服務失敗: %d\n", GetLastError());

return;

}

//初始化,本示例未使用,函數為空

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;

}

//初始化完成,設置運行狀態

SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;

SplSrvServiceStatus.dwCheckPoint = 0;

SplSrvServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){

status = GetLastError();

SvcDebugOut("服務初始化失敗: %d\n", status);

}

//自行修改,用戶完成服務的工作

SvcDebugOut("MiSaKa Servise 運行主線程\n", 0);

return;

}

//初始化工作,這里未進行任何工作,帶讀者修改

DWORD SplSrvServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError){

return 0;

}

//服務控制請求處理函數,與ControlService函數配合

VOID WINAPI SplSrvServiceCtrlHandle(DWORD opcode){

DWORD status;

switch (opcode){

case SERVICE_CONTROL_PAUSE:

//完成相關功能

SplSrvServiceStatus.dwCurrentState = SERVICE_PAUSED;

break;

case SERVICE_CONTROL_CONTINUE:

//完成相關功能

SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;

break;

case SERVICE_CONTROL_STOP:

//完成相關功能

SplSrvServiceStatus.dwWin32ExitCode = 0;

SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;

SplSrvServiceStatus.dwCheckPoint = 0;

SplSrvServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){

status = GetLastError();

SvcDebugOut("設置服務狀態錯誤 %ld\n", status);

}

SvcDebugOut("MiSaKa Service 服務結束,控制碼 %ld\n ", opcode);

break;

case SERVICE_CONTROL_INTERROGATE:

//完成相關功能 收到此請求發出響聲,演示服務控制請求的處理過程,可執行修改

MessageBeep(MB_OK);

break;

default:

SvcDebugOut("未知的控制指令 %ld\n", opcode);

}

//當前狀態

if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){

status = GetLastError();

SvcDebugOut("設置服務狀態錯誤 %ld\n", status);

}

return;

}

//顯示信息給調試器

VOID SvcDebugOut(LPSTR String, DWORD Status){

CHAR Buffer[1024];

if (strlen(String)< 1000){

wsprintf(Buffer, String, Status);

OutputDebugString(Buffer);

}

}

//主函數

void main(){

//設置SERVICE_TABLE_ENTRY結構,以NULL結束

//作為StartServiceCtrlDispatcher函數的參數

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;//全局服務句柄

SC_HANDLE schSCManager;//SCM句柄

LPTSTR szServiceName = TEXT("MiSaKaService");//服務名

//創建服務 SCM句柄 服務程序路徑 服務名

BOOL CreateSampleService(SC_HANDLE schSCManager, LPTSTR szPath, LPSTR szServiceName){

schService = CreateService(

schSCManager,//SCM句柄

szServiceName,//服務名

TEXT("御坂網絡服務"),//顯示的服務名

SERVICE_ALL_ACCESS,//存取權限

SERVICE_WIN32_OWN_PROCESS,//服務類別

SERVICE_DEMAND_START,//啟動類別

SERVICE_ERROR_NORMAL,//錯誤控制類別

szPath,//服務的可執行文件路徑

NULL,//不屬于任何用戶組

NULL,//使用已存在的標簽

NULL,//獨立服務

NULL,//本地系統賬戶

NULL//密碼為空

);

if (schService == NULL){

printf("創建服務失敗 %d\n", GetLastError());

return FALSE;

} else{

printf("創建服務成功\n");

CloseServiceHandle(schService);

return TRUE;

}

}

//刪除服務 服務的名字

BOOL DeleteSampleService(LPTSTR szNameOfService){

schService = OpenService(

schSCManager,//SCM句柄

szNameOfService,//服務名

DELETE//可刪除

);

if (schService == NULL){

printf("打開服務失敗 %d\n", GetLastError());

return FALSE;

}

//刪除服務

if (!DeleteService(schService)){

printf("刪除服務失敗 %d\n", GetLastError());

return FALSE;

} else{

printf("刪除服務成功\n");

}

CloseServiceHandle(schService);

return TRUE;

}

//啟動服務 SCM句柄 服務名

BOOL StartSampleService(SC_HANDLE schSCManager, LPTSTR szServiceName){

SC_HANDLE schService;

SERVICE_STATUS_PROCESS ssStatus;

DWORD dwOldCheckPoint;

DWORD dwStartTickCount;

DWORD dwWaitTime;

DWORD dwBytesNeeded;

//打開服務

schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);

if (schService == NULL){

return 0;

}

//啟動服務

if (!StartService(

schService,//服務的句柄

0,//參數個數為0

NULL//參數指針為NULL,沒有參數

)){

printf("啟動服務失敗 %u", GetLastError());

return 0;

} else{

printf("服務啟動成功...\n");

}

//驗證狀態

if (!QueryServiceStatusEx(

schService,//服務的句柄

SC_STATUS_PROCESS_INFO,//服務狀態信息

&ssStatus,//結構體地址

sizeof(SERVICE_STATUS_PROCESS),//結構體大小

&dwBytesNeeded//存儲狀態信息所用的字節數

)){

return 0;

}

//tick count & checkpoint

dwStartTickCount = GetTickCount();

dwOldCheckPoint = ssStatus.dwCheckPoint;

//查詢狀態,確定PENDING狀態結束

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,//服務的句柄

SC_STATUS_PROCESS_INFO,//服務狀態信息

&ssStatus,//結構體地址

sizeof(SERVICE_STATUS_PROCESS),//結構體大小

&dwBytesNeeded//存儲狀態信息所用的字節數

)){

break;

}

if (ssStatus.dwCheckPoint>dwOldCheckPoint){

//進程創建中

dwStartTickCount = GetTickCount();

dwOldCheckPoint = ssStatus.dwCheckPoint;

} else{

if (GetTickCount() - dwStartTickCount>ssStatus.dwWaitHint){

//WaitHint 時間到

break;

}

}

}

//關閉句柄

CloseServiceHandle(schService);

//判斷是否創建成功 狀態由 PENDING 變為 RUNNING

if (ssStatus.dwCurrentState == SERVICE_RUNNING){

printf("創建服務成功\n");

return 1;

} else{

printf("創建服務失敗:\n");

printf("當前開始 %d\n", ssStatus.dwCurrentState);

printf("退出代碼 %d\n", ssStatus.dwWin32ExitCode);

printf("服務特定退出代碼 %d\n", ssStatus.dwServiceSpecificExitCode);

printf("檢查點 %d\n", ssStatus.dwCheckPoint);

printf("等待提示 %d\n", ssStatus.dwWaitHint);

return 0;

}

}

//向服務發送控制碼

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;

}

//打開服務

schService = OpenService(

schSCManager,//SCM句柄

szServiceName,//服務名

fdwAccess//存取權限

);

if (schService == NULL){

printf("打開服務失敗 %d\n", GetLastError());

return FALSE;

}

//發送控制碼

if (!ControlService(

schService,//服務句柄

fdwControl,//控制碼

&ssStatus//狀態

)){

printf("控制服務失敗 %d\n", GetLastError());

return FALSE;

}

//顯示狀態

printf("御坂網絡服務狀態:\n");

printf("服務類型 0x%x\n", ssStatus.dwServiceType);

printf("當前狀態 0x%x\n", ssStatus.dwCurrentState);

printf("接受控制 0x%x\n", ssStatus.dwControlsAccepted);

printf("退出代碼 %d\n", ssStatus.dwWin32ExitCode);

printf("服務特定退出代碼 %d\n", ssStatus.dwServiceSpecificExitCode);

printf("檢查點 %d\n", ssStatus.dwCheckPoint);

printf("等待提示 %d\n", ssStatus.dwWaitHint);

return TRUE;

}

//停止服務 SCM句柄 服務名 是否結束依賴的服務 超時

DWORD StopService(SC_HANDLE hSCM, LPTSTR szServiceName, BOOL fStopDependencies, DWORD dwTimeout){

SERVICE_STATUS_PROCESS ssp;

SERVICE_STATUS ss;

DWORD dwStartTime = GetTickCount();

DWORD dwBytesNeeded;

//打開服務

SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);

//查詢狀態,確定是否已經停止

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狀態,則只需等待

while (ssp.dwCurrentState == SERVICE_STOP_PENDING){

Sleep(ssp.dwWaitHint);

//循環查詢,知道狀態改變

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;

}

}

//先結束依賴服務

if (fStopDependencies){

DWORD i;

DWORD dwBytesNeeded;

DWORD dwCount;

LPENUM_SERVICE_STATUS lpDependencies = NULL;

ENUM_SERVICE_STATUS ess;

SC_HANDLE hDepService;

//使用0大小的buf,獲取buf的大小

//如果EnumDependentServices函數返回從,說明沒有依賴服務

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();

}

//獲得依賴服務

if (!EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount)){

return GetLastError();

}

for (i = 0; i< dwCount; i++){

ess = *(lpDependencies + i);

//打開服務

hDepService = OpenService(hSCM, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);

if (!hDepService){

return GetLastError();

}

//結束服務

if (!ControlService(hDepService, SERVICE_CONTROL_STOP, &ss)){

return GetLastError();

}

//等待服務結束

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;

}

}

}

//關閉服務

CloseServiceHandle(hDepService);

}

//是否內存

HeapFree(GetProcessHeap(), 0, lpDependencies);

}

}

//所有依賴服務以及結束,技術指定服務

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;

//構造服務可執行程序的路徑

GetModuleFileName(NULL, szBinFilePath, MAX_PATH);

pTemp = szBinFilePath + lstrlen(szBinFilePath);

while (*--pTemp != '\\');

lstrcpy(pTemp, TEXT("\\MiSaKaService.exe"));

//打開SCM

schSCManager = OpenSCManager(

NULL,//本機

NULL,//ServicesActive數據庫

SC_MANAGER_ALL_ACCESS//完全存取權限

);

if (schSCManager == NULL){

printf("打開SCM失敗 %d\n", GetLastError());

}

//創建服務

CreateSampleService(schSCManager, szBinFilePath, szServiceName);

//啟動服務

StartSampleService(schSCManager, szServiceName);

//發送請求控制

ControlSampleService(SERVICE_CONTROL_INTERROGATE);

ControlSampleService(SERVICE_CONTROL_CONTINUE);

//停止服務

dwStopError = StopService(schSCManager, szServiceName, TRUE, 1000);

if (dwStopError == ERROR_SUCCESS){

printf("服務成功停止\n");

} else{

printf("服務停止失敗\n");

}

//刪除服務

DeleteSampleService(szServiceName);

CloseServiceHandle(schSCManager);

getchar();

return 0;

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容