在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