说明
第一个程序是服务,第二个程序控制服务 好像需要管理员权限,不然启动失败..
效果
服务程序 名字是 MiSaKaService.exe 在同一个文件夹中
源码
#include
SERVICE_STATUS SplSrvServiceStatus;
SERVICE_STATUS_HANDLE SplSrvServiceStatusHandle;
VOID SvcDebugOut(LPSTR String, DWORD Status);
VOID WINAPI SplSrvServiceCtrlHandle(DWORD opcode);
VOID WINAPI SplSrvServiceStart(DWORD argc, LPTSTR *argv);
DWORD SplSrvServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError);
//启动服务函数
VOID WINAPI SplSrvServiceStart(DWORD argc, LPTSTR *argv){
DWORD status;
DWORD specificError;
//填充结构
SplSrvServiceStatus.dwServiceType = SERVICE_WIN32;
SplSrvServiceStatus.dwCurrentState = SERVICE_START_PENDING;//服务在运行
SplSrvServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
SplSrvServiceStatus.dwWin32ExitCode = 0;
SplSrvServiceStatus.dwServiceSpecificExitCode = 0;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
//注册服务控制请求处理例程
SplSrvServiceStatusHandle = RegisterServiceCtrlHandler(
"MiSaKaService",//服务名
//SERVICE_WIN32_OWN_PROCESS在插件服务时使用了,所以本参数忽略
SplSrvServiceCtrlHandle//控制请求处理函数名
);
if (SplSrvServiceStatusHandle == (SERVICE_STATUS_HANDLE)0){
SvcDebugOut("注册服务失败: %d\n", GetLastError());
return;
}
//初始化,本示例未使用,函数为空
status = SplSrvServiceInitialization(argc, argv, &specificError);
//初始化失败
if (status != NO_ERROR){
SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
SplSrvServiceStatus.dwWin32ExitCode = status;
SplSrvServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus);
return;
}
//初始化完成,设置运行状态
SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){
status = GetLastError();
SvcDebugOut("服务初始化失败: %d\n", status);
}
//自行修改,用户完成服务的工作
SvcDebugOut("MiSaKa Servise 运行主线程\n", 0);
return;
}
//初始化工作,这里未进行任何工作,带读者修改
DWORD SplSrvServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError){
return 0;
}
//服务控制请求处理函数,与ControlService函数配合
VOID WINAPI SplSrvServiceCtrlHandle(DWORD opcode){
DWORD status;
switch (opcode){
case SERVICE_CONTROL_PAUSE:
//完成相关功能
SplSrvServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
//完成相关功能
SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
//完成相关功能
SplSrvServiceStatus.dwWin32ExitCode = 0;
SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;
SplSrvServiceStatus.dwCheckPoint = 0;
SplSrvServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){
status = GetLastError();
SvcDebugOut("设置服务状态错误 %ld\n", status);
}
SvcDebugOut("MiSaKa Service 服务结束,控制码 %ld\n ", opcode);
break;
case SERVICE_CONTROL_INTERROGATE:
//完成相关功能 收到此请求发出响声,演示服务控制请求的处理过程,可执行修改
MessageBeep(MB_OK);
break;
default:
SvcDebugOut("未知的控制指令 %ld\n", opcode);
}
//当前状态
if (!SetServiceStatus(SplSrvServiceStatusHandle, &SplSrvServiceStatus)){
status = GetLastError();
SvcDebugOut("设置服务状态错误 %ld\n", status);
}
return;
}
//显示信息给调试器
VOID SvcDebugOut(LPSTR String, DWORD Status){
CHAR Buffer[1024];
if (strlen(String)< 1000){
wsprintf(Buffer, String, Status);
OutputDebugString(Buffer);
}
}
//主函数
void main(){
//设置SERVICE_TABLE_ENTRY结构,以NULL结束
//作为StartServiceCtrlDispatcher函数的参数
SERVICE_TABLE_ENTRY DispatchTable[] = {
{ "MiSaKaService" ,(LPSERVICE_MAIN_FUNCTION)SplSrvServiceStart},
{NULL,NULL}
};
if (!StartServiceCtrlDispatcher(DispatchTable)){
SvcDebugOut("MiSaKa Service StartServiceCtrlDispatcher 错误 %d\n", GetLastError());
}
}
源码
#include
#include
SC_HANDLE schService;//全局服务句柄
SC_HANDLE schSCManager;//SCM句柄
LPTSTR szServiceName = TEXT("MiSaKaService");//服务名
//创建服务 SCM句柄 服务程序路径 服务名
BOOL CreateSampleService(SC_HANDLE schSCManager, LPTSTR szPath, LPSTR szServiceName){
schService = CreateService(
schSCManager,//SCM句柄
szServiceName,//服务名
TEXT("御坂网络服务"),//显示的服务名
SERVICE_ALL_ACCESS,//存取权限
SERVICE_WIN32_OWN_PROCESS,//服务类别
SERVICE_DEMAND_START,//启动类别
SERVICE_ERROR_NORMAL,//错误控制类别
szPath,//服务的可执行文件路径
NULL,//不属于任何用户组
NULL,//使用已存在的标签
NULL,//独立服务
NULL,//本地系统账户
NULL//密码为空
);
if (schService == NULL){
printf("创建服务失败 %d\n", GetLastError());
return FALSE;
} else{
printf("创建服务成功\n");
CloseServiceHandle(schService);
return TRUE;
}
}
//删除服务 服务的名字
BOOL DeleteSampleService(LPTSTR szNameOfService){
schService = OpenService(
schSCManager,//SCM句柄
szNameOfService,//服务名
DELETE//可删除
);
if (schService == NULL){
printf("打开服务失败 %d\n", GetLastError());
return FALSE;
}
//删除服务
if (!DeleteService(schService)){
printf("删除服务失败 %d\n", GetLastError());
return FALSE;
} else{
printf("删除服务成功\n");
}
CloseServiceHandle(schService);
return TRUE;
}
//启动服务 SCM句柄 服务名
BOOL StartSampleService(SC_HANDLE schSCManager, LPTSTR szServiceName){
SC_HANDLE schService;
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwOldCheckPoint;
DWORD dwStartTickCount;
DWORD dwWaitTime;
DWORD dwBytesNeeded;
//打开服务
schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
if (schService == NULL){
return 0;
}
//启动服务
if (!StartService(
schService,//服务的句柄
0,//参数个数为0
NULL//参数指针为NULL,没有参数
)){
printf("启动服务失败 %u", GetLastError());
return 0;
} else{
printf("服务启动成功...\n");
}
//验证状态
if (!QueryServiceStatusEx(
schService,//服务的句柄
SC_STATUS_PROCESS_INFO,//服务状态信息
&ssStatus,//结构体地址
sizeof(SERVICE_STATUS_PROCESS),//结构体大小
&dwBytesNeeded//存储状态信息所用的字节数
)){
return 0;
}
//tick count & checkpoint
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
//查询状态,确定PENDING状态结束
while (ssStatus.dwCurrentState == SERVICE_START_PENDING){
//等待一段时间爱你
dwWaitTime = ssStatus.dwWaitHint / 10;
if (dwWaitTime< 1000){
dwWaitTime = 1000;
} else if (dwWaitTime>10000){
dwWaitTime = 10000;
}
Sleep(dwWaitTime);
//再次查询
if (!QueryServiceStatusEx(
schService,//服务的句柄
SC_STATUS_PROCESS_INFO,//服务状态信息
&ssStatus,//结构体地址
sizeof(SERVICE_STATUS_PROCESS),//结构体大小
&dwBytesNeeded//存储状态信息所用的字节数
)){
break;
}
if (ssStatus.dwCheckPoint>dwOldCheckPoint){
//进程创建中
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
} else{
if (GetTickCount() - dwStartTickCount>ssStatus.dwWaitHint){
//WaitHint 时间到
break;
}
}
}
//关闭句柄
CloseServiceHandle(schService);
//判断是否创建成功 状态由 PENDING 变为 RUNNING
if (ssStatus.dwCurrentState == SERVICE_RUNNING){
printf("创建服务成功\n");
return 1;
} else{
printf("创建服务失败:\n");
printf("当前开始 %d\n", ssStatus.dwCurrentState);
printf("退出代码 %d\n", ssStatus.dwWin32ExitCode);
printf("服务特定退出代码 %d\n", ssStatus.dwServiceSpecificExitCode);
printf("检查点 %d\n", ssStatus.dwCheckPoint);
printf("等待提示 %d\n", ssStatus.dwWaitHint);
return 0;
}
}
//向服务发送控制码
BOOL ControlSampleService(DWORD fdwControl){
SERVICE_STATUS ssStatus;
DWORD fdwAccess;
DWORD dwStartTickCount;
DWORD dwWaitTime;
switch (fdwControl){
case SERVICE_CONTROL_STOP:
fdwAccess = SERVICE_STOP;
break;
case SERVICE_CONTROL_PAUSE:
caseSERVICE_CONTROL_CONTINUE:
fdwAccess = SERVICE_PAUSE_CONTINUE;
break;
case SERVICE_CONTROL_INTERROGATE:
fdwAccess = SERVICE_INTERROGATE;
break;
default:
fdwAccess = SERVICE_INTERROGATE;
}
//打开服务
schService = OpenService(
schSCManager,//SCM句柄
szServiceName,//服务名
fdwAccess//存取权限
);
if (schService == NULL){
printf("打开服务失败 %d\n", GetLastError());
return FALSE;
}
//发送控制码
if (!ControlService(
schService,//服务句柄
fdwControl,//控制码
&ssStatus//状态
)){
printf("控制服务失败 %d\n", GetLastError());
return FALSE;
}
//显示状态
printf("御坂网络服务状态:\n");
printf("服务类型 0x%x\n", ssStatus.dwServiceType);
printf("当前状态 0x%x\n", ssStatus.dwCurrentState);
printf("接受控制 0x%x\n", ssStatus.dwControlsAccepted);
printf("退出代码 %d\n", ssStatus.dwWin32ExitCode);
printf("服务特定退出代码 %d\n", ssStatus.dwServiceSpecificExitCode);
printf("检查点 %d\n", ssStatus.dwCheckPoint);
printf("等待提示 %d\n", ssStatus.dwWaitHint);
return TRUE;
}
//停止服务 SCM句柄 服务名 是否结束依赖的服务 超时
DWORD StopService(SC_HANDLE hSCM, LPTSTR szServiceName, BOOL fStopDependencies, DWORD dwTimeout){
SERVICE_STATUS_PROCESS ssp;
SERVICE_STATUS ss;
DWORD dwStartTime = GetTickCount();
DWORD dwBytesNeeded;
//打开服务
SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);
//查询状态,确定是否已经停止
if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
return GetLastError();
}
if (ssp.dwControlsAccepted == SERVICE_STOPPED){
return ERROR_SUCCESS;
}
//如果是STOP_PENDING状态,则只需等待
while (ssp.dwCurrentState == SERVICE_STOP_PENDING){
Sleep(ssp.dwWaitHint);
//循环查询,知道状态改变
if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
return GetLastError();
}
if (ssp.dwCurrentState == SERVICE_STOPPED){
return ERROR_SUCCESS;
}
if (GetTickCount() - dwStartTime>dwTimeout){
return ERROR_TIMEOUT;
}
}
//先结束依赖服务
if (fStopDependencies){
DWORD i;
DWORD dwBytesNeeded;
DWORD dwCount;
LPENUM_SERVICE_STATUS lpDependencies = NULL;
ENUM_SERVICE_STATUS ess;
SC_HANDLE hDepService;
//使用0大小的buf,获取buf的大小
//如果EnumDependentServices函数返回从,说明没有依赖服务
if (!EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount)){
if (GetLastError() != ERROR_MORE_DATA){
return GetLastError();//意外的错误
}
lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);
if (!lpDependencies){
return GetLastError();
}
//获得依赖服务
if (!EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount)){
return GetLastError();
}
for (i = 0; i< dwCount; i++){
ess = *(lpDependencies + i);
//打开服务
hDepService = OpenService(hSCM, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
if (!hDepService){
return GetLastError();
}
//结束服务
if (!ControlService(hDepService, SERVICE_CONTROL_STOP, &ss)){
return GetLastError();
}
//等待服务结束
while (ss.dwCurrentState != SERVICE_STOPPED){
Sleep(ss.dwWaitHint);
if (!QueryServiceStatusEx(hDepService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
if (ss.dwCurrentState == SERVICE_STOPPED){
break;
}
if (GetTickCount() - dwStartTime>dwTimeout){
return ERROR_TIMEOUT;
}
}
}
//关闭服务
CloseServiceHandle(hDepService);
}
//是否内存
HeapFree(GetProcessHeap(), 0, lpDependencies);
}
}
//所有依赖服务以及结束,技术指定服务
if (!ControlService(hService, SERVICE_CONTROL_STOP, &ss)){
return GetLastError();
}
while (ss.dwCurrentState != SERVICE_STOPPED){
Sleep(ss.dwWaitHint);
if(!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)){
return GetLastError();
}
if (ss.dwCurrentState == SERVICE_STOPPED){
break;
}
if (GetTickCount()-dwStartTime>dwTimeout){
return ERROR_TIMEOUT;
}
}
return ERROR_SUCCESS;
}
int main(int argc, TCHAR *argv[]){
TCHAR szBinFilePath[MAX_PATH];
PTCHAR pTemp;
DWORD dwStopError;
//构造服务可执行程序的路径
GetModuleFileName(NULL, szBinFilePath, MAX_PATH);
pTemp = szBinFilePath + lstrlen(szBinFilePath);
while (*--pTemp != '\\');
lstrcpy(pTemp, TEXT("\\MiSaKaService.exe"));
//打开SCM
schSCManager = OpenSCManager(
NULL,//本机
NULL,//ServicesActive数据库
SC_MANAGER_ALL_ACCESS//完全存取权限
);
if (schSCManager == NULL){
printf("打开SCM失败 %d\n", GetLastError());
}
//创建服务
CreateSampleService(schSCManager, szBinFilePath, szServiceName);
//启动服务
StartSampleService(schSCManager, szServiceName);
//发送请求控制
ControlSampleService(SERVICE_CONTROL_INTERROGATE);
ControlSampleService(SERVICE_CONTROL_CONTINUE);
//停止服务
dwStopError = StopService(schSCManager, szServiceName, TRUE, 1000);
if (dwStopError == ERROR_SUCCESS){
printf("服务成功停止\n");
} else{
printf("服务停止失败\n");
}
//删除服务
DeleteSampleService(szServiceName);
CloseServiceHandle(schSCManager);
getchar();
return 0;
}