一個服務(wù)程序

說明

第一個程序是服務(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;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內(nèi)容