创建一个windows服务

本文介绍了如何使用C++实现Windows服务,包括服务注册、状态管理、控制处理和文件日志记录。重点讲解了服务的启动、停止、创建和删除操作,以及如何通过命令行参数控制服务行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsvc.h>
#include <stdio.h>

#define SLEEP_TIME 5000
#define LOG_FILE L"C:\\Users\\wjr\\Desktop\\log\\service.log"
#define SERVICE_NAME    L"wjrtest"
#define SERVICE_DISPLAY_NAME L"我的测试服务"
#define SERVICE_DESCRIPTION	 L"我的第一个测试服务" 

SERVICE_STATUS    ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
SC_HANDLE scm;
SC_HANDLE scv;

void ServiceMain(int argc, LPWSTR* argv);
void ControlHandler(DWORD request);
void Log(const char* msg);
int startFunc();
void OnStart();
void OnCreate();
void OnDelete();
void OnStop();
void writeServiceDescription();


int main(int argc, char* argv[])
{
	SERVICE_TABLE_ENTRY ServiceTable[2] =
	{
		{ (LPWSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
		{ NULL,NULL }
	};
	Log("启动Main");
	if (argc == 2)
	{
		if (!strcmp(argv[1], "-create"))
		{
			OnCreate();
			return 0;
		}
		else if (!strcmp(argv[1], "-delete"))
		{
			OnDelete();
			return 0;
		}
		else if (!strcmp(argv[1], "-start"))
		{
			OnStart();
			return 0;
		}
		else if (!strcmp(argv[1], "-stop"))
		{
			OnStop();
			return 0;
		}
		else
		{
			Log("参数错误\n");
			return 0;
		}
	}


	StartServiceCtrlDispatcher(ServiceTable);
	return 0;
}

void Log(const char* str)
{
	SYSTEMTIME time;
	GetLocalTime(&time);
	char buf[3000] = { 0 };	
	sprintf_s(buf, 3000, "%04d-%02d-%02d %02d:%02d:%02d [%lu] [%lu] %s\r\n", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond,GetCurrentProcessId(), GetCurrentThreadId(),str);

	FILE* fp = NULL;
	_wfopen_s(&fp, LOG_FILE, L"a+");
	if (fp == NULL)
	{
		printf("error to open file: %d\n", GetLastError());
		return;
	}
	fprintf(fp, "%s", buf);
	fflush(fp);
	fclose(fp);
}

void ServiceMain(int argc, LPWSTR* argv)
{
	Log("ServiceMain");
	BOOL bRet;	
	bRet = TRUE;
	ServiceStatus.dwWin32ExitCode = 0;
	ServiceStatus.dwCheckPoint = 0;
	ServiceStatus.dwWaitHint = 0;
	ServiceStatus.dwServiceType = SERVICE_WIN32;
	ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
	ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
	ServiceStatus.dwServiceSpecificExitCode = 0;

	hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)ControlHandler);
	if (hStatus == (SERVICE_STATUS_HANDLE)0)
	{
		Log("服务器启动失败");
		return;
	}
	//service status update
	ServiceStatus.dwCurrentState = SERVICE_RUNNING;
	SetServiceStatus(hStatus, &ServiceStatus);

	while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
	{		
		Log("I am runing");
		Sleep(5000);
	}
	Log("程序退出");
	ServiceStatus.dwCurrentState = SERVICE_STOPPED;
	SetServiceStatus(hStatus, &ServiceStatus);
}

int startFunc()
{
	MessageBox(NULL, L"startFunc", SERVICE_NAME, MB_OK);
	return 0;
}

void ControlHandler(DWORD request)
{
	//主要这个线程和ServiceMain不是一个线程
	switch (request)
	{
	case SERVICE_CONTROL_STOP:
		Log("SERVICE_CONTROL_STOP");
		//标识正在停止
		ServiceStatus.dwWin32ExitCode = 0;
		ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
		SetServiceStatus(hStatus, &ServiceStatus);
		return;

	case SERVICE_CONTROL_SHUTDOWN:
		Log("SERVICE_CONTROL_SHUTDOWN");
		ServiceStatus.dwWin32ExitCode = 0;
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		SetServiceStatus(hStatus, &ServiceStatus);
		return;
	default:
		break;
	}

	SetServiceStatus(hStatus, &ServiceStatus);
}

void OnCreate()
{
	WCHAR filename[MAX_PATH];
	DWORD dwErrorCode;
	GetModuleFileName(NULL, filename, MAX_PATH);
	Log("Creating Service .... ");
	scm = OpenSCManager(0/*localhost*/,
		NULL/*SERVICES_ACTIVE_DATABASE*/,
		SC_MANAGER_ALL_ACCESS/*ACCESS*/);
	if (scm == NULL)
	{
		printf("OpenSCManager error:%d\n", GetLastError());
		return;
	}
	scv = CreateService(scm,//句柄
		SERVICE_NAME,//服务开始名
		SERVICE_DISPLAY_NAME,//显示服务名
		SERVICE_ALL_ACCESS, //服务访问类型
		//SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,//服务类型
		SERVICE_WIN32_OWN_PROCESS,
		SERVICE_AUTO_START, //自动启动服务
		SERVICE_ERROR_NORMAL,//忽略错误
		filename,//启动的文件名
		NULL,//name of load ordering group (载入组名)
		NULL,//标签标识符
		NULL,//相关性数组名
		NULL,//帐户(当前)
		NULL); //密码(当前)

	if (scv == NULL)
	{
		dwErrorCode = GetLastError();
		if (dwErrorCode != ERROR_SERVICE_EXISTS)
		{
			printf("Failure !\n");
			CloseServiceHandle(scm);
			return;
		}
		else
		{
			printf("already Exists !\n");
		}
	}
	else
	{
		printf("Success !\n");
		CloseServiceHandle(scv);

	}

	CloseServiceHandle(scm);
	scm = scv = NULL;

	//注册表写入
	writeServiceDescription();
}

void writeServiceDescription()
{
	HKEY resultKey = NULL;
	WCHAR buf[1000] = { 0 };
	wsprintf(buf, L"SYSTEM\\CurrentControlSet\\Services\\%s", SERVICE_NAME);
	LSTATUS status = RegOpenKey(HKEY_LOCAL_MACHINE, buf, &resultKey);
	if (status != ERROR_SUCCESS)
	{
		Log("注册表打开失败");
		return;
	}
	int size = (int)wcslen(SERVICE_DESCRIPTION) * sizeof(WCHAR);
	status = RegSetValueEx(resultKey, L"Description", 0, REG_SZ, (const BYTE*)SERVICE_DESCRIPTION, size);
	if (status != ERROR_SUCCESS)
	{
		Log("写入服务器描述失败");
	}
	RegCloseKey(resultKey);
}


void OnDelete()
{
	scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (scm != NULL)
	{
		scv = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
		if (scv != NULL)
		{
			QueryServiceStatus(scv, &ServiceStatus);
			if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
			{
				ControlService(scv, SERVICE_CONTROL_STOP, &ServiceStatus);
			}
			DeleteService(scv);
			CloseServiceHandle(scv);
		}
		CloseServiceHandle(scm);
	}
	scm = scv = NULL;
}


void OnStart()
{
	DWORD dwErrorCode;
	//Starting Service
	Log("Starting Service .... ");
	scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (scm != NULL)
	{
		scv = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
		if (scv != NULL)
		{
			if (StartService(scv, 0, NULL) == 0)
			{
				dwErrorCode = GetLastError();
				if (dwErrorCode == ERROR_SERVICE_ALREADY_RUNNING)
				{
					printf("already Running !\n");
					CloseServiceHandle(scv);
					CloseServiceHandle(scm);
					return;
				}
			}
			else
			{
				printf("Pending ... ");
			}

			//wait until the servics started
			while (QueryServiceStatus(scv, &ServiceStatus) != 0)
			{
				if (ServiceStatus.dwCurrentState == SERVICE_START_PENDING)
				{
					Sleep(100);

				}
				else
				{
					break;

				}
			}

			CloseServiceHandle(scv);
		}
		else
		{
			//error to OpenService
			printf("error to OpenService\n");
		}

		CloseServiceHandle(scm);
	}
	else
	{
		printf("error to OpenSCManager\n");
	}
	scm = scv = NULL;
	printf("Start Success\n");
}


void OnStop()
{
	scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (scm != NULL)
	{
		scv = OpenService(scm, SERVICE_NAME, SERVICE_STOP | SERVICE_QUERY_STATUS);
		if (scv != NULL)
		{
			QueryServiceStatus(scv, &ServiceStatus);
			if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
			{
				ControlService(scv, SERVICE_CONTROL_STOP, &ServiceStatus);
			}
			CloseServiceHandle(scv);
		}
		CloseServiceHandle(scm);
	}
	scm = scv = NULL;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值