一个服务程序

说明

第一个程序是服务,第二个程序控制服务 好像需要管理员权限,不然启动失败..

效果

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

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容