我得先总结一下步骤:

一、在main函数中的操作
1.先创建一个main主函数,在main主函数中创建创建一个服务程序入口函数列的结构体并将其初始化
机构体SERVICE_TABLE_ENTRY DispatchTable[2];
假设定义的服务入口函数是(LPSERVICE_MAIN_FUNCTION)ServiceMain0
2.由服务程序入口函数表启动一个新服务程序线程
SERVICE_TABLE_ENTRY DispatchTable[2]

二、在(LPSERVICE_MAIN_FUNCTION)ServiceMain0函数中的操作
3.在服务程序入口主函数中,创建一个服务状态的结构体,并将其初始化SERVICE_STATUS
SERVICE_STATUS m_ServiceStatus;
4.注册服务状态控制函数
SERVICE_STATUS_HANDLE m_ServiceStatusHandle = RegisterServiceCtrlHandler(“zcm_service0”,(LPHANDLER_FUNCTION)ServiceCtrlHandler0);
注册服务状态控制函数后,会返回一个操作状态服务函数的句柄,注册成功之后,其实服务就已经开始运行了
5.修改服务程序的工作状态,并将修改后的状态报告SCM管理程序
//修改服务状态
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
//报告运行状态到mc
SetServiceStatus(m_ServiceStatusHandle,&m_ServiceStatus);
6.状态报告给SCM管理程序后,我们的服务就可以正常进行了,用一个while(bRunning)循环,不断处理各种情况,提供服务

三、服务状态管理程序(LPHANDLER_FUNCTION)ServiceCtrlHandler0) 函数中的操作
对服务程序的启动、停止、暂停、恢复功能进行操作
根据传递的参数,用switch(dwControl )对各种状态情况进行处理
1.当收到不同的状态时,将采取一定的操作,控制第二步(LPSERVICE_MAIN_FUNCTION)ServiceMain0函数中的操作
switch(Opcode)
{
case SERVICE_CONTROL_STOP:
bRunning = FALSE;
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
break;
case SERVICE_CONTROL_SHUTDOWN:
bRunning = FALSE;
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
break;
default:
break;
}
2.ServiceMain0函数响应状态后,并执行了相关的操作,那么,再次报告工作状态给scm管理程序

对服务管理程序中的三个函数的分工和之前的联系进行说明,这也正是软件设计步骤,后面就是详细的参数和函数的具体使用

服务程序编好之后,不能双击执行,有三种方法进行操作
1.使用Services.msc程序进行可视化的编辑,操纵服务工作状态,缺点是不能添加我们写的程序到服务列表中
2.使用mc.exe程序进行控制zcm为我创建的服务名
mc.exe create zcm binpath= c:\zcm_service.exe //创建服务
mc.exe query zcm //查询服务状态
mc.exe start zcm //启动服务
mc.exe stop zcm //停止服务
mc.exe delete zcm //卸载服务


3.编写代码来控制SCM,自动化的处理方法,推荐

1.SERVICE_STATUS 是服务状态结构,用于标记服务的状态

typedef struct _SERVICE_STATUS {DWORD   dwServiceType; //服务可执行文件的类型DWORD   dwCurrentState;DWORD   dwControlsAccepted;DWORD   dwWin32ExitCode;DWORD   dwServiceSpecificExitCode;DWORD   dwCheckPoint;DWORD   dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;

dwServiceType 的取值说明:

// Service Types (Bit Mask)
#define SERVICE_WIN32_OWN_PROCESS      0x00000010 //可执行文件中只有一个单独的服务
#define SERVICE_WIN32_SHARE_PROCESS    0x00000020 //拥有多个服务
#define SERVICE_WIN32                  (SERVICE_WIN32_OWN_PROCESS | \SERVICE_WIN32_SHARE_PROCESS) // win32程序服务
#define SERVICE_INTERACTIVE_PROCESS    0x00000100  //服务需要和桌面发生交互#define SERVICE_KERNEL_DRIVER          0x00000001 //核心服务
#define SERVICE_FILE_SYSTEM_DRIVER     0x00000002 //文件系统服务
#define SERVICE_ADAPTER                0x00000004 //适配器服务
#define SERVICE_RECOGNIZER_DRIVER      0x00000008#define SERVICE_DRIVER                 (SERVICE_KERNEL_DRIVER | \SERVICE_FILE_SYSTEM_DRIVER | \SERVICE_RECOGNIZER_DRIVER)#define SERVICE_INTERACTIVE_PROCESS    0x00000100#define SERVICE_TYPE_ALL               (SERVICE_WIN32  | \SERVICE_ADAPTER | \SERVICE_DRIVER  | \SERVICE_INTERACTIVE_PROCESS)

dwCurrentState 用于通知SCManger

// Service State -- for CurrentState
//
#define SERVICE_STOPPED                        0x00000001 //服务停止
#define SERVICE_START_PENDING                  0x00000002 //初始态,用于初始化,将要开始运行服务
#define SERVICE_STOP_PENDING                   0x00000003 //将要停止服务
#define SERVICE_RUNNING                        0x00000004 //服务正在运行
#define SERVICE_CONTINUE_PENDING               0x00000005 //将要暂停后继续
#define SERVICE_PAUSE_PENDING                  0x00000006 //将要暂停
#define SERVICE_PAUSED                         0x00000007 //服务已暂停

dwControlsAccepted 服务接受什么样的控制通知

// Controls Accepted  (Bit Mask)
//
#define SERVICE_ACCEPT_STOP                    0x00000001 //该服务可以被停止
#define SERVICE_ACCEPT_PAUSE_CONTINUE          0x00000002 //该服务可以被暂停和继续
#define SERVICE_ACCEPT_SHUTDOWN                0x00000004 //当系统关闭时通知该服务
#define SERVICE_ACCEPT_PARAMCHANGE             0x00000008 //该服务可以在不停止和重启的情况下重新读取其启动参数
#define SERVICE_ACCEPT_NETBINDCHANGE           0x00000010 //该服务是一个网络成分,可在不停止和重启的情况下接受绑定的变化
#define SERVICE_ACCEPT_HARDWAREPROFILECHANGE   0x00000020
#define SERVICE_ACCEPT_POWEREVENT              0x00000040
#define SERVICE_ACCEPT_SESSIONCHANGE           0x00000080
#define SERVICE_ACCEPT_PRESHUTDOWN             0x00000100 //该服务可执行预关闭任务
#define SERVICE_ACCEPT_TIMECHANGE              0x00000200
#define SERVICE_ACCEPT_TRIGGEREVENT            0x00000400

dwWin32ExitCode:错误码,用于在服务启动或关闭时报错;默认设置为0
dwServiceSpecificExitCode:特定于服务的错误码,用于在服务启动或关闭时报错;默认设置为0
dwCheckPoint:检测点值,服务周期性的增加该值,以报告服务在一段长期时间内所做的启动,停止,暂停,继续的处理;默认设置为0
dwWaitHint:以毫秒为单位的估计时间,用于估计启动、停止、暂停、继续操作的时间;默认设置为0,只有当服务启动超过三十秒时,才进行设置

SERVICE_STATUS_HANDLE 服务状态句柄
RegisterServiceCtrlHandler注册服务状态控制函数,将LPHANDLER_FUNCTION的服务状态函数注册到zcm_service0的服务中去,然后返回一个可操作的服务状态句柄

SERVICE_STATUS_HANDLE m_ServiceStatusHandle = RegisterServiceCtrlHandler("zcm_service0",(LPHANDLER_FUNCTION)ServiceCtrlHandler0);

注册成功服务状态函数后,就可以修改服务的状态信息,将服务由初始化的SERVICE_START_PENDING修改为SERVICE_RUNNING状态

//修改服务状态
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
//报告运行状态到mc
SetServiceStatus(m_ServiceStatusHandle,&m_ServiceStatus);

SERVIcE_STATUS结构体的状态修改后,要将修改后的状态信息设置到scManger管理程序中
RegisterServiceCtrlHandler 注册服务函数

__checkReturn
WINADVAPI
SERVICE_STATUS_HANDLE
WINAPI
RegisterServiceCtrlHandlerA(__in    LPCSTR                    lpServiceName, //服务名称__in    __callbackLPHANDLER_FUNCTION          lpHandlerProc //服务状态控制函数);
__checkReturn
WINADVAPI
SERVICE_STATUS_HANDLE
WINAPI
RegisterServiceCtrlHandlerW(__in    LPCWSTR                    lpServiceName,__in    __callbackLPHANDLER_FUNCTION          lpHandlerProc);
#ifdef UNICODE
#define RegisterServiceCtrlHandler  RegisterServiceCtrlHandlerW
#else
#define RegisterServiceCtrlHandler  RegisterServiceCtrlHandlerA
#endif // !UNICODE

SetServiceStatus 服务状态设置函数,修改服务状态后,要将服务状态设置到scm管理器中

WINADVAPI
BOOL
WINAPI
SetServiceStatus(__in        SERVICE_STATUS_HANDLE   hServiceStatus, //服务状态操作句柄__in        LPSERVICE_STATUS        lpServiceStatus //SERVICE_STATUS状态结构体指针);

LPHANDLER_FUNCTION服务状态控制函数,还有一个Ex的版本

//
// Prototype for the Service Control Handler Function
//typedef VOID (WINAPI *LPHANDLER_FUNCTION)(DWORD    dwControl //状态参数);typedef DWORD (WINAPI *LPHANDLER_FUNCTION_EX)(DWORD    dwControl, //状态参数DWORD    dwEventType,LPVOID   lpEventData,LPVOID   lpContext);

dwControl状态控制

/ Controls
//
#define SERVICE_CONTROL_STOP                   0x00000001 //停止
#define SERVICE_CONTROL_PAUSE                  0x00000002 //暂停
#define SERVICE_CONTROL_CONTINUE               0x00000003 //继续
#define SERVICE_CONTROL_INTERROGATE            0x00000004 //查询
#define SERVICE_CONTROL_SHUTDOWN               0x00000005 //关机时
#define SERVICE_CONTROL_PARAMCHANGE            0x00000006 //参数变化进
#define SERVICE_CONTROL_NETBINDADD             0x00000007 //网络绑定时
#define SERVICE_CONTROL_NETBINDREMOVE          0x00000008
#define SERVICE_CONTROL_NETBINDENABLE          0x00000009
#define SERVICE_CONTROL_NETBINDDISABLE         0x0000000A
#define SERVICE_CONTROL_DEVICEEVENT            0x0000000B
#define SERVICE_CONTROL_HARDWAREPROFILECHANGE  0x0000000C
#define SERVICE_CONTROL_POWEREVENT             0x0000000D
#define SERVICE_CONTROL_SESSIONCHANGE          0x0000000E
#define SERVICE_CONTROL_PRESHUTDOWN            0x0000000F
#define SERVICE_CONTROL_TIMECHANGE             0x00000010
#define SERVICE_CONTROL_TRIGGEREVENT           0x00000020

Service服务入口表,如果是一个程序入口程,则将结构体设置成2个成员的数组,如果是2个入口函数,则设置成员为3,最后一个成员的服务名和入口函数都要设置为NULL

// Service Start Table
//typedef struct _SERVICE_TABLE_ENTRYA {LPSTR                       lpServiceName; //服务名LPSERVICE_MAIN_FUNCTIONA    lpServiceProc; //服务程序入口函数
}SERVICE_TABLE_ENTRYA, *LPSERVICE_TABLE_ENTRYA;
typedef struct _SERVICE_TABLE_ENTRYW {LPWSTR                      lpServiceName;LPSERVICE_MAIN_FUNCTIONW    lpServiceProc;
}SERVICE_TABLE_ENTRYW, *LPSERVICE_TABLE_ENTRYW;
#ifdef UNICODE
typedef SERVICE_TABLE_ENTRYW SERVICE_TABLE_ENTRY;
typedef LPSERVICE_TABLE_ENTRYW LPSERVICE_TABLE_ENTRY;
#else
typedef SERVICE_TABLE_ENTRYA SERVICE_TABLE_ENTRY;
typedef LPSERVICE_TABLE_ENTRYA LPSERVICE_TABLE_ENTRY;
#endif // UNICODE

在main主函数中启动一个线程,用于创建一个新的线程
//定义并初始化一个服务入口函数表
SERVICE_TABLE_ENTRY DispatchTable[2];
DispatchTable[0].lpServiceName = “zcm_service0”;
DispatchTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain0;
DispatchTable[1].lpServiceName = NULL;//“zcm_service1”;
DispatchTable[1].lpServiceProc = NULL;//(LPSERVICE_MAIN_FUNCTION)ServiceMain1;
//根据服务入口函数表,创建一个新的线程
StartServiceCtrlDispatcher(DispatchTable);

下而是实例程序

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define SLEEP_TIME 5000
#define LOG_FILE_NAME "C:\\Documents and Settings\\Administrator\\My Documents\\visual studio 2010\\Projects\\zcm_service\\Debug\\debug.log"BOOL bRunning = TRUE;//是否运行,控制主函数
SERVICE_STATUS m_ServiceStatus; //服务状态结构
SERVICE_STATUS_HANDLE m_ServiceStatusHandle; //服务状态句柄void WINAPI ServiceMain0(int argc,char* argv[]);
//void WINAPI ServiceMain1(int argc,char* argv[]);void ServiceCtrlHandler0(DWORD Opcode);
//void ServiceCtrlHandler1(DWORD Opcode);void WriteToLog(LPTSTR szStr);int main(int argc,char* argv[])
{//创建服务程序入口函数表SERVICE_TABLE_ENTRY DispatchTable[2];DispatchTable[0].lpServiceName = "zcm_service0";DispatchTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain0;DispatchTable[1].lpServiceName = NULL;//"zcm_service1";DispatchTable[1].lpServiceProc = NULL;//(LPSERVICE_MAIN_FUNCTION)ServiceMain1;//DispatchTable[2].lpServiceName = NULL;//DispatchTable[2].lpServiceProc = NULL;//创建一个新的线程StartServiceCtrlDispatcher(DispatchTable);return 0;
}//服务入口主函数
void WINAPI ServiceMain0(int argc,char* argv[])
{MEMORYSTATUS memstatus;TCHAR szBuffer[256];int avaible_MB = 0;memset(szBuffer,0,256);//初始化服务状态m_ServiceStatus.dwServiceType = SERVICE_WIN32;m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE;m_ServiceStatus.dwWin32ExitCode = 0;m_ServiceStatus.dwServiceSpecificExitCode = 0;m_ServiceStatus.dwCheckPoint = 0;m_ServiceStatus.dwWaitHint = 0;//注册服务状态控制函数m_ServiceStatusHandle = RegisterServiceCtrlHandler("zcm_service0",(LPHANDLER_FUNCTION)ServiceCtrlHandler0);if(m_ServiceStatusHandle == 0){WriteToLog("RegisterServiceCtrlHandler ERROR!");return;}else{WriteToLog("RegisterServiceCtrlHandler OK!");}//修改服务状态m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;//报告运行状态到mcSetServiceStatus(m_ServiceStatusHandle,&m_ServiceStatus);bRunning = TRUE;while(bRunning){//服务程序的主体GlobalMemoryStatus(&memstatus);avaible_MB = memstatus.dwAvailPhys / 1024 /1024;wsprintf(szBuffer,"Memory:%d",avaible_MB);WriteToLog(szBuffer);Sleep(SLEEP_TIME);}//bRunning = FALSEm_ServiceStatus.dwCurrentState = SERVICE_STOP;SetServiceStatus(m_ServiceStatusHandle,&m_ServiceStatus);WriteToLog("Program is Stoped!");return;
}//服务控制函数
//启动、停止、暂停、恢复操作,对这些功能进行操作
void ServiceCtrlHandler0(DWORD Opcode)
{switch(Opcode){case SERVICE_CONTROL_STOP:bRunning = FALSE;m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;break;case SERVICE_CONTROL_SHUTDOWN:bRunning = FALSE;m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;break;default:break;}SetServiceStatus(m_ServiceStatusHandle,&m_ServiceStatus);
}void WriteToLog(LPSTR szStr)
{FILE* fp;fopen_s(&fp,LOG_FILE_NAME,"a+");if(!fp){return ;}fprintf(fp,"%s\n",szStr);fclose(fp);
}

50.服务程序SERVICE_STATUS、SERVICE_STATUS_HANDLE、RegisterServiceCtrlHandler、SetServiceStatus、SERVICE_TABL相关推荐

  1. Windows 服务程序编写

    摘要:几乎所有的操作系统在启动的时候都会启动一些不需要与用户交互的进程,这些进程在Windows中就被称作服务.它由服务程序.服务控制程序(SCP,service control program)和服 ...

  2. Windows 服务程序(一)

    借鉴此博客 https://www.cnblogs.com/M-Anonymous/p/9393088.html Windows 服务程序简介: Windows服务应用程序是一种需要长期运行的应用程序 ...

  3. windows服务程序一

    Windows 服务程序简介: Windows服务应用程序是一种需要长期运行的应用程序,它没有用户界面,并且也不会产生任何可视输出.计算机启动时,服务会自动开始运行.Windows服务允许用户创建可在 ...

  4. WINDOWS服务开发

    1.查看系统日志:控制面板\所有控制面板项\管理工具\计算机管理 2.windows服务的实现: 资料:msdn->system service->services. http://msd ...

  5. Windows服务编写综述

    作者:李朝中 摘要:几乎所有的操作系统在启动的时候都会启动一些不需要与用户交互的进程,这些进程在Windows中就被称作服务.它由服务程序.服务控制程序(SCP,service control pro ...

  6. Windows服务编写

    摘要:几乎所有的操作系统在启动的时候都会启动一些不需要与用户交互的进程,这些进程在Windows中就被称作服务.它由服务程序.服务控制程序(SCP,service control program)和服 ...

  7. windows服务编写原理(下)

    二)对服务的深入讨论之上 上一章其实只是概括性的介绍,下面开始才是真正的细节所在.在进入点函数里面要完成ServiceMain的初始化,准确点说是初始化一个SERVICE_TABLE_ENTRY结构数 ...

  8. windows服务编程

    文章目录 前言 方案一:服务程序 方案二:后台程序 对比 windows服务编程 windows服务控制 附录 - 完整代码 前言 在linux中,如果需要一个程序在后台持续提供服务,我们一般会使用守 ...

  9. Winamp头上动土

    Winamp头上动土 遭遇 近日使用Winamp时发生极度不爽的事情,就是我打CS的时候习惯听着Winamp来打,但我的播放列表又很乱,有些我不想听的歌也在播放列表里面,我又懒得去整理,所以有时正要杀 ...

最新文章

  1. 差异基因分析:fold change(差异倍数), P-value(差异的显著性)
  2. python大神-Python大神都是这样处理XML文件的!
  3. tensorflow 语义slam_【论文阅读28】DynaSLAM
  4. java.util.ComparableTimSort中的sort()方法简单分析
  5. P4564 [CTSC2018]假面(期望)
  6. android 安装assets中的apk,如何安装assets下apk,附源码(原创)
  7. Java多线程系列(四):4种常用Java线程锁的特点,性能比较、使用场景
  8. 让visual连接sqlserver数据库
  9. 20210612:力扣第244周周赛题解(上)
  10. php更新用户数据为空,php - 使用PHP更新数据库,而没有来自HTML表单的空值 - SO中文参考 - www.soinside.com...
  11. javascript设计模式实践之策略模式--输入验证
  12. 基于java飞机大战游戏
  13. Python大屏看板最全教程之数据库连接
  14. LightBulb – 保护视力,自动根据时间调整显示器伽马值
  15. 【友盟+】国庆假期旅游类APP使用报告(中)
  16. LeetCode 276:栅栏涂色
  17. Fault Description Based Attribute Transfer for Zero-Sample Industrial Fault Diagnosis
  18. 谷歌公司经典面试题扔鸡蛋的详细解读(一)
  19. 日语笔记(2) 动词ます形
  20. Autocad2004与win7和谐共处。

热门文章

  1. 对短视频应该持有的正确态度-今抖云创
  2. 阿哔,你飘了呀~ 大胆! 阿哔也是你叫的? 叫哔哥!
  3. 三星android7.0新特性,三星Galaxy S7升级安卓7.0牛轧糖新特性:分辨率可调
  4. 达达技术架构演化之路
  5. CPU的Cache和TLB系统原理
  6. java8List.sort()排序常用方法
  7. Word十大使用技巧。
  8. 虚拟战争史——关于VR如何改变未来
  9. 苹果亮度突然变暗_苹果最好的旗舰手机,iPhone11Pro Max你用上了吗?
  10. Adaptive Autosar 整体架构理解