Win32服务程序编写

在Windows中,有一个特殊的群体,他们天生拥有极高的权限,在一些特殊用户,比如“SYSTEM”的用户中工作。他们享受很高的优待。很多系统功能(更新服务,触摸屏服务。。。)都是以服务运行的

WIn32程序编写需要用到的函数详解:

BOOL WINAPI StartServiceCtrlDispatcher(
In const SERVICE_TABLE_ENTRY *lpServiceTable
);
函数功能:连接到服务控制管理器
参数:一个SERVICE_TABLE_ENTRY结构的指针,成员表中的最后一项必须具有NULL值,来指定表的末尾。
如果 此 函数 成功 , 返回 值 不 为零 。 如果 函数 失败 , 返回 值 为 零 。
typedef struct _SERVICE_TABLE_ENTRY {
LPTSTR lpServiceName;
LPSERVICE_MAIN_FUNCTION lpServiceProc;
} SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;
lpServiceName:要在此服务进程中运行的服务名称,不能和其他程序的重了。我一般把这个名称设为注册到系统的服务名称一致。
如果服务安装的是SERVICE_WIN32_OWN_PROCESS服务类型,此成员将被忽略,但不能为 NULL,可以是空字符串("")。
lpServiceProc:指针,指向ServiceMain函数。

VOID WINAPI ServiceMain(
In DWORD dwArgc,
In LPTSTR *lpszArgv
);
dwArgc:lpszArgv数组中字符串个数
lpszArgv:启动参数

SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerEx(
In LPCTSTR lpServiceName,
In LPHANDLER_FUNCTION_EX lpHandlerProc,
In_opt LPVOID lpContext
);
函数功能:注册一个函数来处理扩展的服务控制请求。
lpServiceName:通过调用线程运行的服务的名称。这是服务控制程序在创建服务时,CreateService函数中指定的服务名称。(和上面说的SERVICE_TABLE_ENTRY中的lpServiceName一致即可)
lpHandlerProc:指向要注册的处理程序函数(HandlerEx)的指针
lpContext:上下文。当多个服务共享一个进程,表示任何用户定义的数据。此参数传递给处理程序函数,可以帮助识别服务。(可空)
如果 此 函数 成功 , 返回 值 是 服务 状态 的 句柄 。 如果 函数 失败 , 返回 值 为 零。

DWORD WINAPI HandlerEx(
In DWORD dwControl,
In DWORD dwEventType,
In LPVOID lpEventData,
In LPVOID lpContext
);
用 RegisterServiceCtrlHandlerEx 函数 应用程序定义 的 回调 函数 。 服务 程序 可以 使用 它 作为 控制 处理程序 功能 的 特定 服务 。

BOOL WINAPI SetServiceStatus(
In SERVICE_STATUS_HANDLE hServiceStatus,
In LPSERVICE_STATUS lpServiceStatus
);
hServiceStatus: 当前 服务 的 状态 信息 结构 的 句柄 。 此 句柄 是 由 RegisterServiceCtrlHandlerEx 函数 返回 的 。
lpServiceStatus: 指向 SERVICE_STATUS 结构 的 指针,此结构 包含 调用 服务 的 最新 状态 信息 。
如果 此 函数 成功 , 返回 值 不 为零 。 如果 函数 失败 , 返回 值 为 零 。

使用步骤:

生成之后的可执行文件,放到C盘的根目录下面,便于我们进行操作:
打开cmd使用命令行参数进行程序的创建(管理员身份打开):
使用sc命令创建的格式为:
sc + create + 服务程序的名字 + binpath= + 程序路径
启动sc start …
查看:services.msc
例子:

sc create aaaaaa binpath=C:\Users\pengqing\Desktop\代码程序\empty_demo\Debug\empty_demo.exe

sc start aaaaaa

services.msc

以下是Win32服务程序编程例子

#include < windows.h >
#include < stdio.h >
#include <stdlib.h>
#include <string>
#include <tchar.h>
// MyServices.cpp : 定义控制台应用程序的入口点。
//
#include <atltime.h>

#define  SLEEP_TIME 5000 //两次连续查询可用内存之前毫秒间隔
#define  LOGFILE "C:/test/test.txt"//日志文件路径,将获取的内容写入文件

SERVICE_STATUS                      ServiceStatus;
SERVICE_STATUS_HANDLE   hStatus;
bool brun;

int WriteToLog(char* str)
{
	FILE* fp = NULL;
	errno_t err = fopen_s( &fp, LOGFILE,"a+");
	//fp = fopen_s(LOGFILE,"a+");
	if (fp)
	{
		CTime ct =  CTime::GetCurrentTime();
		CString strTime  = ct.Format("%Y-%m-%d,%H:%M:%S(%c)");//系统时间
		fprintf_s(fp,strTime);
		fprintf_s(fp,"%s\n",str);
		fclose(fp);
		return 0;
	}
	return - 1;
}

//服务初始化
int InitService()
{
	int result = WriteToLog("Monitoring Started");
	return result;
}

void WINAPI Ctrlhandler(DWORD request)
{
	switch (request)
	{
	case SERVICE_CONTROL_STOP:
		brun = false;
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		break;
	case SERVICE_CONTROL_SHUTDOWN:
		brun = false;
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		break;
	case SERVICE_CONTROL_PAUSE:
		brun = false;
		ServiceStatus.dwCurrentState = SERVICE_PAUSED;
		break;
	case SERVICE_CONTROL_CONTINUE:
		brun = false;
		ServiceStatus.dwCurrentState = SERVICE_RUNNING;
		break;
	default:
		break;
	}
	//向SCM报告“SERVICE_STOPPED”状态
	SetServiceStatus(hStatus,&ServiceStatus);
}

VOID ServiceMain(
				 DWORD   dwNumServicesArgs,
				 LPWSTR  *lpServiceArgVectors)
{
	//服务类型,创建win32服务
	ServiceStatus.dwServiceType = SERVICE_WIN32;
	//服务当前状态,在这里的时候初始化未完成,所以pending
	ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
	//通知SCM服务接收哪个域,处理控制请求后面处理
	ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN
		| SERVICE_ACCEPT_STOP;//本例只接受系统关机和停止服务2种控制命令
	//终止服务并报告退出细节,初始化时不退出,将他们赋值为0
	ServiceStatus.dwWin32ExitCode =  0;
	ServiceStatus.dwServiceSpecificExitCode = 0;
	//表示初始化某个服务进程要30s以上,因为我们的实例初始化过程很短,设置为0
	ServiceStatus.dwCheckPoint = 0;
	ServiceStatus.dwWaitHint = 0;
	//为服务注册控制处理器
	hStatus = RegisterServiceCtrlHandler("MemoryStatus",Ctrlhandler);//服务名,指向controlhandlefunction指针
	if (!hStatus)
	{
		WriteToLog("RegisterServerCtrlhandler Failed");
		return;
	}
	WriteToLog("RegisterServiceCtrlHandler Sucess");
	//
	if(InitService() == -1)
	{
		//初始化失败,可能写日志文件失败
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		ServiceStatus.dwWin32ExitCode = -1;
		SetServiceStatus(hStatus,&ServiceStatus);
		//退出serviceMain
		return;
	}
	//
	//向sCM报告运行服务状态
	ServiceStatus.dwCurrentState = SERVICE_RUNNING;
	BOOL bstatus = SetServiceStatus(hStatus,&ServiceStatus);
	if(!bstatus)
	{
		DWORD  derror = GetLastError();
		char str[100]={0};
		sprintf_s(str,100,"SetServiceStatus Failed,The error value is %d",derror);
		WriteToLog(str);
		return;
	}
	//下面就开始任务循环,添加自己希望的服务
	//这里是每隔5s查询一次可用物理内存并写入日志
	MEMORYSTATUS memstatus;
	brun = true;
	while (brun)
	{
		char str[100]={0};
		GlobalMemoryStatus(&memstatus);
		int iavailmb = memstatus.dwAvailPhys/1024/1024;
		sprintf_s(str,100,"available memory is %d MB",iavailmb);
		WriteToLog(str);
		Sleep(SLEEP_TIME);
	}
	WriteToLog("Service Stopped");
}

//创建分派表并启动控制分派机
int _tmain(int argc, _TCHAR* argv[])
{
	SERVICE_TABLE_ENTRY ServiceTable[2];
	ServiceTable[0].lpServiceName = "MemoryStatus";
	ServiceTable[0].lpServiceProc = 
		(LPSERVICE_MAIN_FUNCTION)ServiceMain;

	ServiceTable[1].lpServiceName = NULL;
	ServiceTable[1].lpServiceProc = NULL;
	//启动服务的控制分派机线程
	StartServiceCtrlDispatcher(ServiceTable);
	return 0;
}

转载:
http://blog.youkuaiyun.com/zuishikonghuan/article/details/47604179
https://blog.youkuaiyun.com/weixin_42100963/article/details/104204122

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值