目录
1.关于windows标准可执行程序和服务程序
2.服务相关整理
2.1 VC++编写服务
2.2 服务注册
2.3 服务卸载
2.4 启动服务
2.5 关闭服务
2.6 sc命令
2.7 查看服务
3.标准程序
3.1 后台方式运行标准程序
3.2 查找进程
3.3 终止进程
以前经常在Linux下编写服务器程序,服务器程序大多都是以守护进程方式运行,并且很多都是要开机启动方式进行。最近工作需要编写跨平台的服务,所以就 想了解一下windows下服务开发,通过查询资料发现windows服务完全是另外一回事,windows没有linux那种以&方式运行服务器程序的方式,需要单独使用另外一套api来开发。
1.关于windows标准可执行程序和服务程序
Window 标准的exe可执行程序通常有一个用户界面,Console或GUI,通常由用户来启动或停止.
Windows服务是运行在windows后台指定用户下(默认System)的应用程序,它没有标准的UI界面,相比标准的EXE程序,Windows服务是在服务开始的时候创建,而在服务结束的时候销毁,而且可以设置服务是否与操作系统一起启动,一起关闭。
它支持三种方式:1)自动方式 2)手动方式 3)禁用 。
自动方式的时候,windows服务将在OS启动后自动启动运行,而手动方式则必须手工启动服务,禁用的情况下服务将不能被启动。另外标准的EXE默认使用的当前登录的用户,而windows服务则默认使用System用户,这在对系统资源访问的时候特别需要注意。
Windows Service 是主要用于服务器环境而长期运行的应用程序, 这类程序不需要有用户界面或者任何模拟输出。 任何的用户消息通常都是记录在Windows 事件日志里。Windows Service可以在操作系统启动的时候开始,一直在后台运行,当有需要时也可以手动启动,我们可以通过管理工具里面的服务进行统一管理。当系统启动完毕后,Windows服务并不需要通过登陆页面后才能启动,而我们启动一般的exe文件却要先登陆Windows后才能启动它。
Windows Service 是一种可随 Windows 操作系统启动而启动的,在后台运行的,通常不和用户产生交互的程序。它无法通过双击来运行,类似于 Unix 守护进程(daemon processes),当用户注销时它也不会停止。
Windows 服务由三部分组成:1.一个服务可执行文件;2.一个服务控制程序(SCP);3.服务控制管理器(SCM),
负责在 HKLM\SYSTEM\CurrentControlSet\Services 下创建服务键值。用户可通过 SCP 控制服务的启动、停止、暂停等,SCP 会通过 SCM 调用服务程序。服务程序、服务控制程序(SCP,service control program)和服务控制管理器(SCM,service control manager)组成了Windows服务。我们可以通过服务控制程序操纵服务控制管理器来配置、启动、暂停、停止服务程序。其中服务程序和服务控制程序可以由我们自己来编写扩展,而服务控制管理器(\windows\system32\servics.exe)则是操作系统内置的一个部件。
重点说明:
Windows服务程序其实并不神秘,它只是遵循特定规则编写的一个程序。只要遵循这个特定的规则与服务控制管理器正确的交互,就可实现我们的服务程序。而我们只要能实现一个简单的服务程序,设计一个能处理复杂业务的服务也并非难事,因为从结构上看两者并没有太大的区别。
只要遵循与SCM交互的规则,设计服务程序与设计普通的应用程序几乎没什么区别。
2.服务相关整理
2.1 VC++编写服务
// MyService.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <Windows.h>
#include <iostream>using namespace std;/*
BOOL IsInstalled();
BOOL Install();
BOOL Uninstall();
void LogEvent(LPCTSTR pszFormat, ...);
void WINAPI ServiceMain();
void WINAPI ServiceStrl(DWORD dwOpcode);TCHAR szServiceName[] = _T("MyService");
BOOL bInstall;
SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS status;
DWORD dwThreadID;
SC_HANDLE hSCM;
SC_HANDLE hService;
*//*
OpenSCManager 用于打开服务控制管理器;
CreateService 用于创建服务;
OpenService用于打开已有的服务,返回该服务的句柄;
ControlService则用于控制已打开的服务状态,这里是让服务停止后才删除;
DeleteService 用于删除指定服务。RegisterServiceCtrlHandler 注册服务控制
*///定义全局函数变量
void Init();
BOOL IsInstalled();
BOOL Install();
BOOL Uninstall();
void LogEvent(LPCTSTR pszFormat, ...);
void WINAPI ServiceMain();
void WINAPI ServiceStrl(DWORD dwOpcode);TCHAR szServiceName[] = _T("MyService");
BOOL bInstall;
SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS status;
DWORD dwThreadID;int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{Init();dwThreadID = ::GetCurrentThreadId();SERVICE_TABLE_ENTRY st[] ={{ szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },{ NULL, NULL }};if (_stricmp(lpCmdLine, "/install") == 0){Install();}else if (_stricmp((LPCTSTR)lpCmdLine, "/uninstall") == 0){Uninstall();}else{if (!::StartServiceCtrlDispatcher(st)){LogEvent(_T("Register Service Main Function Error!"));}}return 0;
}//初始化
void Init()
{hServiceStatus = NULL;status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;status.dwCurrentState = SERVICE_START_PENDING;status.dwControlsAccepted = SERVICE_ACCEPT_STOP;status.dwWin32ExitCode = 0;status.dwServiceSpecificExitCode = 0;status.dwCheckPoint = 0;status.dwWaitHint = 0;
}//服务主函数,这在里进行控制对服务控制的注册
void WINAPI ServiceMain()
{status.dwCurrentState = SERVICE_START_PENDING;status.dwControlsAccepted = SERVICE_ACCEPT_STOP;//注册服务控制 hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceStrl);if (hServiceStatus == NULL){LogEvent(_T("Handler not installed"));return;}SetServiceStatus(hServiceStatus, &status);status.dwWin32ExitCode = S_OK;status.dwCheckPoint = 0;status.dwWaitHint = 0;status.dwCurrentState = SERVICE_RUNNING;SetServiceStatus(hServiceStatus, &status);//模拟服务的运行。应用时将主要任务放于此即可 //可在此写上服务需要执行的代码,一般为死循环 while (1){FILE *p;p = fopen("c:\\log.txt", "ab+");SYSTEMTIME st;GetSystemTime(&st);char time[100] = { 0 };_sntprintf(time, 100, "%4d-%02d-%02d %02d:%02d:%02d\r\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);fwrite(time, strlen(time), 1, p);fclose(p);Sleep(1000);}status.dwCurrentState = SERVICE_STOPPED;SetServiceStatus(hServiceStatus, &status);
}//Description: 服务控制主函数,这里实现对服务的控制,
// 当在服务管理器上停止或其它操作时,将会运行此处代码
void WINAPI ServiceStrl(DWORD dwOpcode)
{switch (dwOpcode){case SERVICE_CONTROL_STOP:status.dwCheckPoint = 1;status.dwCurrentState = SERVICE_STOP_PENDING;SetServiceStatus(hServiceStatus, &status);Sleep(500);status.dwCheckPoint = 0;status.dwCurrentState = SERVICE_STOPPED;SetServiceStatus(hServiceStatus, &status);PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);break;case SERVICE_CONTROL_PAUSE:break;case SERVICE_CONTROL_CONTINUE:break;case SERVICE_CONTROL_INTERROGATE:break;case SERVICE_CONTROL_SHUTDOWN:exit(0);break;default:LogEvent(_T("Bad service request"));}
}//判断服务是否已经被安装
BOOL IsInstalled()
{BOOL bResult = FALSE;//打开服务控制管理器 SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (hSCM != NULL){//打开服务 SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_QUERY_CONFIG);if (hService != NULL){bResult = TRUE;::CloseServiceHandle(hService);}::CloseServiceHandle(hSCM);}return bResult;
}//安装服务函数
BOOL Install()
{//检测是否安装过if (IsInstalled())return TRUE;//打开服务控制管理器 SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (hSCM == NULL){MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);return FALSE;}//获取程序目录TCHAR szFilePath[MAX_PATH];::GetModuleFileName(NULL, szFilePath, MAX_PATH);//创建服务 SC_HANDLE hService = ::CreateService(hSCM, szServiceName, szServiceName,SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,szFilePath, NULL, NULL, _T(""), NULL, NULL);//检测创建是否成功if (hService == NULL){::CloseServiceHandle(hSCM);MessageBox(NULL, _T("Couldn't create service"), szServiceName, MB_OK);return FALSE;}//释放资源::CloseServiceHandle(hService);::CloseServiceHandle(hSCM);return TRUE;
}//删除服务函数
BOOL Uninstall()
{//检测是否安装过if (!IsInstalled())return TRUE;//打开服务控制管理器SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (hSCM == NULL){MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);return FALSE;}//打开具体服务SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);if (hService == NULL){::CloseServiceHandle(hSCM);MessageBox(NULL, _T("Couldn't open service"), szServiceName, MB_OK);return FALSE;}//先停止服务SERVICE_STATUS status;::ControlService(hService, SERVICE_CONTROL_STOP, &status);//删除服务 BOOL bDelete = ::DeleteService(hService);::CloseServiceHandle(hService);::CloseServiceHandle(hSCM);if (bDelete) return TRUE;LogEvent(_T("Service could not be deleted"));return FALSE;
}//记录服务事件
void LogEvent(LPCTSTR pFormat, ...)
{TCHAR chMsg[256];HANDLE hEventSource;LPTSTR lpszStrings[1];va_list pArg;va_start(pArg, pFormat);_vstprintf(chMsg, pFormat, pArg);va_end(pArg);lpszStrings[0] = chMsg;hEventSource = RegisterEventSource(NULL, szServiceName);if (hEventSource != NULL){ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*)&lpszStrings[0], NULL);DeregisterEventSource(hEventSource);}
}
编译产物如下:
服务程序本身也是PE格式的文件。
2.2 服务注册
MyService.exe /install
2.3 服务卸载
MyService.exe /uninstall
可以看到服务已经被删除
2.4 启动服务
net start MyService
2.5 关闭服务
net stop MyService
2.6 sc命令
sc命令可以用于管理系统服务、计划任务、系统日志等方面,是不可或缺的神器。
(1) 要查看系统服务列表
sc query state=all
(2) 启动或者停止服务
sc start 服务名
sc stop 服务名
(3) 查看服务属性
例如:以CSV格式输出服务的属性
sc query 服务名 /format:csv
(4) 创建服务
sc create HelloWorldService binPath= "D:\VC\vcDemo\Debug\helloworld.exe"
(5) 山存储服务
sc delete HelloWorldService
实战演示
创建服务
sc create MyService binPath= "D:\VC\vcDemo\Debug\MyService.exe"
启动服务
sc start MyService
关闭服务
sc stop MyService
删除服务
sc delete MyService
2.7 查看服务
方法一
services.msc
方法二:
电脑 - 右键管理
3.标准程序
3.1 后台方式运行标准程序
@ECHO OFF
%1 start mshta vbscript:createobject("wscript.shell").run("""%~0"" ::",0)(window.close)&&exit
start /b helloworld.exe
3.2 查找进程
tasklist | findstr hello
3.3 终止进程
@ECHO OFF
taskkill /im helloworld.exe /f
微软官方关于服务主函数说明:
编写服务程序主函数 - Win32 apps | Microsoft Learn
关于Windows服务,发现一个写的比较好的博客:
C++之创建Windows系统服务_c++编写windows服务-CSDN博客