C++编写服务程序

来源:互联网 发布:淘宝在线客服在哪里 编辑:程序博客网 时间:2024/06/05 14:22

近段时间,在学习使用C++写windows服务。参考了若干的资料,写如下服务,作为学习笔记。

写服务主要有一下步骤

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;
}

 

曾考虑将服务执行函数和控制请求函数写成类的成员函数。则需要将该成员函数写成静态函数才能成为回调函数。

鄙人菜鸟一枚,对于windows服务知知甚少,请各位大牛不吝赐教!

原创粉丝点击