C++如何编写windwos服务应用

写服务主要有一下步骤

1、使用 StartServiceCtrlDispatcher(SERVICE_TABLE_ENTRY lpServiceStartTable);连接SCM,让SCM控制函数。需要注意的是最后lpServiceStartTable的最后一个结构体的两个属性值都是NULL

2、编写ServiceMain函数,服务执行函数 是结构体SERVICE_TABLE_ENTRY的lpServiceProc属性所指定的值。函数开始就需要调用RegisterServiceCtrlHandler,用于指定

控制请求函数。

3、编写控制请求函数,用于根据在cmd中提供的命令,来控制服务

具体代码如下。
// service_practice.cpp : Defines the entry point for the console application.
#include "stdafx.h"

#include <afxsock.h>
VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);
VOID WINAPI serviceCtrl(DWORD fdwControl);
BOOL initSocket();
int WriteToLog(char* str);
#define LOGFILE "C:\\practice.txt"
SERVICE_STATUS_HANDLE hService;
SERVICE_STATUS serviceStatus;
int main(int argc, char* argv[])
{
// printf("Hello World!\n");
//定义SERVICE_TABLE_ENTRY 结构体
SERVICE_TABLE_ENTRY serviceTable[2];
serviceTable[0].lpServiceName = "servicePractice";
serviceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

serviceTable[1].lpServiceName = NULL;
serviceTable[1].lpServiceProc = NULL;
//connects the main thread of a service process to the service control manager,
//which causes the thread to be the service control dispatcher thread for the calling process.
//连接scm,让scm控制服务
//serviceTable必须要以NULL,NULL为最后一项
WriteToLog("注册服务函数开始");
StartServiceCtrlDispatcher(serviceTable);
WriteToLog("注册服务函数结束");
return 0;
}
/************************************************************************/
/*ServiceMain 服务执行函数 */
/*入参: */
/*DWORD dwArgc number of arguments */
/*LPTSTR *lpszArgv number of arguments */
/*return void */
/*author liuduo */
/*date 20130404 */
/************************************************************************/
VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
{

//在ServiceMain中首先调用RegisterServiceCtrlHandler,指定处理控制请求函数
//返回值用于setServiceStatus报告当前服务状态
WriteToLog("注册服务处理函数开始");
hService = RegisterServiceCtrlHandler("servicePractice",serviceCtrl);
WriteToLog("注册服务处理函数结束");
//定义SERVICE_STATE,用于向SCM报告服务状态

//win32服务运行自己的程序
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
//服务正在启动
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
//服务接收
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE|SERVICE_ACCEPT_SHUTDOWN;
//启动或者停止时的错误代码,当服务正在运行和正常停止是,通常赋值为NO_ERROR
serviceStatus.dwWin32ExitCode = NO_ERROR;
//启动或者停止时发生错误时,指定特定的代码,如果dwWin32ExitCode的值为ERROR_SERVICE_SPECIFIC_ERROR
//时,该字段的值忽略
serviceStatus.dwServiceSpecificExitCode = 0;
//通过该值的增加,来判断现在处于什么运行状态,如果该值不用,则置为0
serviceStatus.dwCheckPoint = 0;
//如果在改时间段内,dwCheckPoint,dwCurrentState都没有发生任何改变,则SCM会任务发生了错误
serviceStatus.dwWaitHint = 1000;
WriteToLog("报告服务正在启动开始");
// SetServiceStatus(hService,&serviceStatus);
WriteToLog("报告服务正在启动结束");
if (WriteToLog("Service Start") == 0)
{
serviceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hService,&serviceStatus);
}


while(SERVICE_RUNNING == serviceStatus.dwCurrentState)
{

//需要执行的操作在此
WriteToLog("正在跑");

Sleep(5000);
}

}
/************************************************************************/
/*serviceCtrl 处理控制请求函数 */
/*入参: */
/*DWORD fdwControl */
/* Value Meaning */
/* SERVICE_CONTROL_STOP 请求停止服务. */
/* SERVICE_CONTROL_PAUSE 请求暂停服务. */
/* SERVICE_CONTROL_CONTINUE 请求暂停的服务继续. */
/* SERVICE_CONTROL_INTERROGATE 请求服务立即更新状态,并汇报给SCM. */
/* SERVICE_CONTROL_SHUTDOWN 请求服务清除所有任务,系统即将关闭服务。 */
/*return void */
/*author liuduo */
/*date 20130404 */
/************************************************************************/
VOID WINAPI serviceCtrl(DWORD fdwControl)
{
switch (fdwControl)
{
case SERVICE_CONTROL_STOP:
//SCM发送停止服务信息需要将服务当前状态设为停止,否则不能正常停止服务
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
serviceStatus.dwWaitHint = 1000;
SetServiceStatus(hService,&serviceStatus);
WriteToLog("服务正在停止");
serviceStatus.dwCurrentState = SERVICE_STOPPED;
// SetServiceStatus(hService,serviceStatus);
break;
case SERVICE_CONTROL_PAUSE:
//SCM发送暂停服务信息需要将服务当前状态设为停止,暂停时间可自定义,超过该时间在若状态不是停止
//则服务不能正常暂停服务
serviceStatus.dwWaitHint = 10000;
serviceStatus.dwCurrentState = SERVICE_PAUSE_PENDING;
SetServiceStatus(hService,&serviceStatus);
WriteToLog("服务正在暂停");
serviceStatus.dwCurrentState = SERVICE_PAUSED;
// SetServiceStatus(hService,serviceStatus);
break;
case SERVICE_CONTROL_CONTINUE:
//SCM发送继续运行信息需要将服务当前状态设为正在运行,否则不能正常运行服务
serviceStatus.dwCurrentState = SERVICE_CONTINUE_PENDING;
SetServiceStatus(hService,&serviceStatus);
WriteToLog("正在继续服务");
serviceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
break;
default:
break;
}
SetServiceStatus(hService,&serviceStatus);
}


int WriteToLog(char* str)
{
FILE* f = fopen(LOGFILE, "a+");
if (f == NULL)
{
return -1;
}
fprintf(f, "%s ", str);
fclose(f);
return 0;
}

 

曾考虑将服务执行函数和控制请求函数写成类的成员函数。则需要将该成员函数写成静态函数才能成为回调函数。
————————————————
版权声明:本文为CSDN博主「ld1060843986」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ld1060843986/article/details/8814117

posted @ 2022-12-15 16:41  IceArrow  阅读(106)  评论(0编辑  收藏  举报