实际中很多场景需要用到服务,如你的业务程序运行在windows系统,当系统重启时,无需用户登录系统要求启动你的程序,这个场景就需要用到windows服务。
windows服务能够在计算机重启时自动启动,不显示任何用户界面。
一:windows服务相关命令 创建windows服务可以使用sc命令
1.创建TestService服务,设置服务显示名称为TestService,开机自启动
sc create TestService binpath= "D:\\test.exe" start= auto displayname= "TestService"
2.设置服务的描述信息
sc description TestService "这是肉哥的测试服务"
3.启动服务
sc start TestService
4.停止服务
sc stop TestService
5.删除服务
sc delete TestService
6.服务恢复属性
服务运行过程中如有用户通过任务管理器把服务运行的进程给关闭了,为保证能够重启该服务进程,可通过配置恢复属性来实现 服务失败三次都是就行了重启,也可以把后续失败来改成运行一个程序。
该配置可以使用如下命令来实现:
sc failure TestService reset= 0 actions= restart/100000/restart/100000/restart/100000
设置服务失败时要运行的命令行
sc failure TestService reset= 0 command= d:\alert.exe actions= run/5000
二:查看服务 cmd命令行运行 services.msc打开服务管理器,界面如下:
三:服务程序实例 这里说下不是任何的win32应用都可以做成服务,需要在程序中加入相应的代码来满足服务的要求。
main函数
main函数中主要分两步:
第一步:初始化一个SERVICE_TABLE_ENTRY 分配表结构体
第二步:调用StartServiceCtrlDispatcher系统函数,把调用进程的主线程转换为控制分派器。该分派器会启动一个新线程,线程运行服务中的ServiceMain()函数。
2.ServiceMain函数
ServiceMain函数是服务的工作函数,业务逻辑放到该函数中。函数格式为:void WINAPI ServiceMain(int argc, char** argv),名字可以任意定义。
ServiceMain执行任务前,由于还没开始执行任务,需要将服务状态设置为SERVICE_START_PENDING,表示正在初始化。 ervicestatus.dwCurrentState = SERVICE_START_PENDING
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 /******************************************************** Copyright (C), 2016-2018, FileName: main Author: 肉哥 Email: CodeRoad666@163.com Created: 2019/12/02 Description: 这是一个用于注册成服务的win32程序 ********************************************************/ #include <stdio.h> #include <iostream> #include <windows.h> using namespace std; #define SERVICE_NAME "TestService" SERVICE_STATUS g_serviceStatus; //服务状态 SERVICE_STATUS_HANDLE g_hServiceStatus; //服务状态句柄 void WINAPI ServiceMain(int argc, char** argv); void WINAPI CtrlHandler(DWORD request); int InitService(); int WriteToLog(char* str); int main(); /************************************ @ Brief: @ Author: woniu201 @ Created: 2019/12/02 @ Return: ************************************/ int WriteToLog(char* str) { FILE* pfile; fopen_s(&pfile, "D:\\log.txt", "a+"); if (pfile==NULL) { return -1; } fprintf_s(pfile,"%s\n",str); fclose(pfile); return 0; } STARTUPINFO si; PROCESS_INFORMATION pi; /************************************ @ Brief: 服务工作函数 @ Author: woniu201 @ Created: 2019/12/02 @ Return: ************************************/ void WINAPI ServiceMain(int argc, char** argv) { WriteToLog("++++++++++++ServiceMain++++++++++++++++"); g_serviceStatus.dwServiceType = SERVICE_WIN32; g_serviceStatus.dwCurrentState = SERVICE_START_PENDING; g_serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;//在本例中只接受系统关机和停止服务两种控制命令 g_serviceStatus.dwWin32ExitCode = 0; g_serviceStatus.dwServiceSpecificExitCode = 0; g_serviceStatus.dwCheckPoint = 0; g_serviceStatus.dwWaitHint = 0; g_hServiceStatus = ::RegisterServiceCtrlHandler(SERVICE_NAME, CtrlHandler); if (g_hServiceStatus==0) { WriteToLog("RegisterServiceCtrlHandler failed"); return; } WriteToLog("RegisterServiceCtrlHandler success"); //向SCM 报告运行状态 g_serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus (g_hServiceStatus, &g_serviceStatus); //执行任务 MEMORYSTATUS memstatus; char str[100] = {0}; memset(str, 0 ,100); while (true) { GlobalMemoryStatus(&memstatus); int availmb=memstatus.dwAvailPhys/1024/1024; sprintf_s(str,100,"Available memory is %dMB",availmb); WriteToLog(str); Sleep(5000); } } /************************************ @ Brief: 服务管理器回调函数 @ Author: woniu201 @ Created: 2019/12/02 @ Return: ************************************/ void WINAPI CtrlHandler(DWORD request) { switch (request) { case SERVICE_CONTROL_STOP: WriteToLog("++++++++++++SERVICE_CONTROL_STOP++++++++++++++++"); g_serviceStatus.dwCheckPoint = 1; g_serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(g_hServiceStatus, &g_serviceStatus); Sleep(5000); g_serviceStatus.dwCheckPoint = 0; g_serviceStatus.dwCurrentState = SERVICE_STOPPED; break; case SERVICE_CONTROL_SHUTDOWN: WriteToLog("++++++++++++SERVICE_CONTROL_SHUTDOWN++++++++++++++++"); g_serviceStatus.dwCurrentState = SERVICE_STOPPED; break; case SERVICE_CONTROL_PAUSE: WriteToLog("++++++++++++SERVICE_CONTROL_SHUTDOWN++++++++++++++++"); break; case SERVICE_CONTROL_INTERROGATE: WriteToLog("++++++++++++SERVICE_CONTROL_INTERROGATE++++++++++++++++"); break; default: break; } SetServiceStatus (g_hServiceStatus, &g_serviceStatus); } int main() { WriteToLog("++++++++++++main++++++++++++++++"); SERVICE_TABLE_ENTRY entrytable[2]; entrytable[0].lpServiceName= SERVICE_NAME; entrytable[0].lpServiceProc=(LPSERVICE_MAIN_FUNCTION)ServiceMain; entrytable[1].lpServiceName=NULL; entrytable[1].lpServiceProc=NULL; StartServiceCtrlDispatcher(entrytable); return 0; }