windows服务例子

该代码示例展示了如何在Windows环境下创建一个服务,包括服务的安装、主函数、控制处理器以及状态报告。服务可以被启动、停止,并通过调试信息跟踪其运行状态。服务安装部分使用了OpenSCManager和CreateService函数,而服务的运行则涉及ServiceMain和ServiceCtrlHandlerEx函数,用于响应服务控制请求。
摘要由CSDN通过智能技术生成
```c

#include <windows.h>



void WINAPI ServiceMain(DWORD argc, WCHAR* argv[]);

DWORD WINAPI ServiceHandlerEx(
	DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext);



static WCHAR* ServiceName = (WCHAR*)L"mySBIESVC";
static SERVICE_STATUS        ServiceStatus;
static SERVICE_STATUS_HANDLE ServiceStatusHandle = NULL;


static int g_checkpoint = 0;



int __stdcall WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	SERVICE_TABLE_ENTRY myServiceTable[] = {
		{ ServiceName, ServiceMain },
		{ NULL, NULL }
	};

	//__debugbreak();

	OutputDebugStringW(L"svc start\r\n");

	if (!StartServiceCtrlDispatcher(myServiceTable))
		return GetLastError();

	OutputDebugStringW(L"svc end\r\n");

	return NO_ERROR;
}

void WINAPI ServiceMain(DWORD argc, WCHAR* argv[])
{
	//__debugbreak();

	OutputDebugStringW(L"svc ServiceMain entry\r\n");

	ServiceStatusHandle = RegisterServiceCtrlHandlerEx(ServiceName, ServiceHandlerEx, NULL);

	if (!ServiceStatusHandle) {
		OutputDebugStringW(L"RegisterServiceCtrlHandlerEx error\r\n");
		return;
	}

	ServiceStatus.dwServiceType = SERVICE_WIN32;
	ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;

	ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
	ServiceStatus.dwCurrentState = SERVICE_RUNNING;

	ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
	ServiceStatus.dwWin32ExitCode = 0;
	ServiceStatus.dwServiceSpecificExitCode = 0;
	ServiceStatus.dwCheckPoint = 1;
	ServiceStatus.dwWaitHint = 15000;

	ULONG status = 0;

	if (!SetServiceStatus(ServiceStatusHandle, &ServiceStatus))
		status = GetLastError();

	if (status == 0) {

		ServiceStatus.dwCurrentState = SERVICE_RUNNING;
		ServiceStatus.dwCheckPoint = g_checkpoint++;
		ServiceStatus.dwWaitHint = 3000;
	}
	else {
		OutputDebugStringW(L"InitializePipe error\r\n");

		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
		ServiceStatus.dwServiceSpecificExitCode = status;

		ServiceStatus.dwCheckPoint = g_checkpoint++;
		ServiceStatus.dwWaitHint = 3000;
	}

	SetServiceStatus(ServiceStatusHandle, &ServiceStatus);

	OutputDebugStringW(L"svc ServiceMain end\r\n");
}


DWORD WINAPI ServiceHandlerEx(
	DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
	if (dwControl == SERVICE_CONTROL_STOP ||
		dwControl == SERVICE_CONTROL_SHUTDOWN)
	{
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		ServiceStatus.dwCheckPoint = g_checkpoint++;
		ServiceStatus.dwWaitHint = 3000;
	}
	else if (dwControl != SERVICE_CONTROL_INTERROGATE)
		return ERROR_CALL_NOT_IMPLEMENTED;

	if (!SetServiceStatus(ServiceStatusHandle, &ServiceStatus))
		return GetLastError();

	return 0;
}
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
//#include "sample.h"

#pragma comment(lib, "advapi32.lib")

#define SVCNAME TEXT("SvcName")
#define SVC_ERROR                        ((DWORD)0xC0020001L)

SERVICE_STATUS          gSvcStatus;
SERVICE_STATUS_HANDLE   gSvcStatusHandle;
HANDLE                  ghSvcStopEvent = NULL;
#define LOGFILE "C:\\MyServices\\SvcName.txt"

VOID SvcInstall(void);
VOID WINAPI SvcCtrlHandler(DWORD);
VOID WINAPI SvcMain(DWORD, LPTSTR*);

VOID ReportSvcStatus(DWORD, DWORD, DWORD);
VOID SvcInit(DWORD, LPTSTR*);
VOID SvcReportEvent(LPTSTR);
int WriteToLog(char*);


//
// Purpose: 
//   Entry point for the process
//
// Note:
//   The main function of a service program calls the StartServiceCtrlDispatcher function to connect to the 
//      service control manager (SCM) and start the control dispatcher thread. The dispatcher thread loops, 
//      waiting for incoming control requests for the services specified in the dispatch table. This thread 
//      returns when there is an error or when all of the services in the process have terminated. When all 
//      services in the process have terminated, the SCM sends a control request to the dispatcher thread 
//      telling it to exit. This thread then returns from the StartServiceCtrlDispatcher call and the process
//      can terminate.
//
// Parameters:
//   None
// 
// Return value:
//   None
//
void __cdecl _tmain(int argc, TCHAR* argv[])
{
	// If command-line parameter is "install", install the service. 
	// Otherwise, the service is probably being started by the SCM.

	if (lstrcmpi(argv[1], TEXT("install")) == 0)
	{
		SvcInstall();
		return;
	}

	// TO_DO: Add any additional services for the process to this table.
	SERVICE_TABLE_ENTRY DispatchTable[] =
	{
		{ (LPWSTR)SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
		{ NULL, NULL }
	};

	DWORD dw_RetCode = -1;

	// This call returns when the service has stopped. 
	// The process should simply terminate when the call returns.

	if (!StartServiceCtrlDispatcher(DispatchTable))
	{
		dw_RetCode = GetLastError();
		MessageBoxEx(NULL, _T("start SvrName service fail!"), NULL, 0, 0);
		SvcReportEvent((WCHAR*)L"StartServiceCtrlDispatcher");
	}
}

//
// Purpose: 
//   Installs a service in the SCM database
//
// Parameters:
//   None
// 
// Return value:
//   None
//
VOID SvcInstall()
{
	SC_HANDLE schSCManager;
	SC_HANDLE schService;
	TCHAR szPath[MAX_PATH];

	if (!GetModuleFileName(NULL, szPath, MAX_PATH))
	{
		printf("Cannot install service (%d)\n", GetLastError());
		return;
	}

	// Get a handle to the SCM database. 

	schSCManager = OpenSCManager(
		NULL,                    // local computer
		NULL,                    // ServicesActive database 
		SC_MANAGER_ALL_ACCESS);  // full access rights 

	if (NULL == schSCManager)
	{
		printf("OpenSCManager failed (%d)\n", GetLastError());
		return;
	}

	// Create the service

	schService = CreateService(
		schSCManager,              // SCM database 
		SVCNAME,                   // name of service 
		SVCNAME,                   // service name to display 
		SERVICE_ALL_ACCESS,        // desired access 
		SERVICE_WIN32_OWN_PROCESS, // service type 
		SERVICE_DEMAND_START,      // start type 
		SERVICE_ERROR_NORMAL,      // error control type 
		szPath,                    // path to service's binary 
		NULL,                      // no load ordering group 
		NULL,                      // no tag identifier 
		NULL,                      // no dependencies 
		NULL,                      // LocalSystem account 
		NULL);                     // no password 

	if (schService == NULL)
	{
		printf("CreateService failed (%d)\n", GetLastError());
		CloseServiceHandle(schSCManager);
		return;
	}
	else printf("Service installed successfully\n");

	CloseServiceHandle(schService);
	CloseServiceHandle(schSCManager);
}

//
// Purpose: 
//   Entry point for the service
//
// Parameters:
//   dwArgc - Number of arguments in the lpszArgv array
//   lpszArgv - Array of strings. The first string is the name of
//     the service and subsequent strings are passed by the process
//     that called the StartService function to start the service.
// 
// Return value:
//   None.
//
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
	// Register the handler function for the service

	gSvcStatusHandle = RegisterServiceCtrlHandler(
		SVCNAME,
		SvcCtrlHandler);

	if (!gSvcStatusHandle)
	{
		SvcReportEvent((WCHAR*)TEXT("RegisterServiceCtrlHandler"));
		return;
	}

	// These SERVICE_STATUS members remain as set here

	gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
	gSvcStatus.dwServiceSpecificExitCode = 0;
	gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE;


	WriteToLog((char*)"in SvrMain(), start Service success!");

	// Report initial status to the SCM

	ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);

	// Perform service-specific initialization and work.

	SvcInit(dwArgc, lpszArgv);
}

//
// Purpose: 
//   The service code
//
// Parameters:
//   dwArgc - Number of arguments in the lpszArgv array
//   lpszArgv - Array of strings. The first string is the name of
//     the service and subsequent strings are passed by the process
//     that called the StartService function to start the service.
// 
// Return value:
//   None
//
VOID SvcInit(DWORD dwArgc, LPTSTR* lpszArgv)
{
	// TO_DO: Declare and set any required variables.
	//   Be sure to periodically call ReportSvcStatus() with 
	//   SERVICE_START_PENDING. If initialization fails, call
	//   ReportSvcStatus with SERVICE_STOPPED.

	// Create an event. The control handler function, SvcCtrlHandler,
	// signals this event when it receives the stop control code.

	ghSvcStopEvent = CreateEvent(
		NULL,    // default security attributes
		TRUE,    // manual reset event
		FALSE,   // not signaled
		NULL);   // no name

	if (ghSvcStopEvent == NULL)
	{
		ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
		return;
	}

	// Report running status when initialization is complete.

	ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);

	// TO_DO: Perform work until service stops.

	while (1)
	{
		// Check whether to stop the service.

		WaitForSingleObject(ghSvcStopEvent, INFINITE);

		ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
		return;
	}
}

//
// Purpose: 
//   Sets the current service status and reports it to the SCM.
//
// Parameters:
//   dwCurrentState - The current state (see SERVICE_STATUS)
//   dwWin32ExitCode - The system error code
//   dwWaitHint - Estimated time for pending operation, 
//     in milliseconds
// 
// Return value:
//   None
//
// NOTE:
//      SCM中对服务进行的可控操作是由SERVICE_STATUS.dwControlsAccepted决定的,所以当服务程序状态发生变化后需要下
//      需要及时向SCM汇报服务当前可接受的操作
//
//
VOID ReportSvcStatus(DWORD dwCurrentState,
	DWORD dwWin32ExitCode,
	DWORD dwWaitHint)
{
	static DWORD dwCheckPoint = 1;

	// Fill in the SERVICE_STATUS structure.

	gSvcStatus.dwCurrentState = dwCurrentState;
	gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
	gSvcStatus.dwWaitHint = dwWaitHint;

	if (dwCurrentState == SERVICE_START_PENDING)
	{
		gSvcStatus.dwControlsAccepted = 0;
	}
	else
	{
		gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
	}

	if ((dwCurrentState == SERVICE_RUNNING) ||
		(dwCurrentState == SERVICE_STOPPED))
	{
		gSvcStatus.dwCheckPoint = 0;
	}
	else
	{
		gSvcStatus.dwCheckPoint = dwCheckPoint++;
	}

	// Report the status of the service to the SCM.
	SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
}

//
// Purpose: 
//   Called by SCM whenever a control code is sent to the service
//   using the ControlService function.
//
// Parameters:
//   dwCtrl - control code
// 
// Return value:
//   None
//
VOID WINAPI SvcCtrlHandler(DWORD dwCtrl)
{
	// Handle the requested control code. 

	switch (dwCtrl)
	{
	case SERVICE_CONTROL_STOP:
		ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);

		// Signal the service to stop.

		SetEvent(ghSvcStopEvent);
		ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);

		return;
	case SERVICE_CONTROL_PAUSE:
		break;
	case SERVICE_CONTROL_CONTINUE:
		break;
	case SERVICE_CONTROL_INTERROGATE:
		break;

	default:
		break;
	}

}

//
// Purpose: 
//   Logs messages to the event log
//
// Parameters:
//   szFunction - name of function that failed
// 
// Return value:
//   None
//
// Remarks:
//   The service must have an entry in the Application event log.

VOID SvcReportEvent(LPTSTR szFunction)
{
	HANDLE hEventSource;
	LPCTSTR lpszStrings[2];
	TCHAR Buffer[80];

	hEventSource = RegisterEventSource(NULL, SVCNAME);

	if (NULL != hEventSource)
	{
		StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());

		lpszStrings[0] = SVCNAME;
		lpszStrings[1] = Buffer;

		ReportEvent(hEventSource,        // event log handle
			EVENTLOG_ERROR_TYPE, // event type
			0,                   // event category
			SVC_ERROR,           // event identifier
			NULL,                // no security identifier
			2,                   // size of lpszStrings array
			0,                   // no binary data
			lpszStrings,         // array of strings
			NULL);               // no binary data

		DeregisterEventSource(hEventSource);
	}
}


/**
*   功能:
*       将日志写入日志文件
*/
int WriteToLog(char* str)
{
	//获取系统时间
	SYSTEMTIME sysTime;
	GetLocalTime(&sysTime);

	char logStr[100] = { 0 };
	sprintf_s(logStr, "%04d-%02d-%02d %02d:%02d:%02d : %s", sysTime.wYear, sysTime.wMonth, sysTime.wDay,
		sysTime.wHour, sysTime.wMinute, sysTime.wSecond, str);

	FILE* logfile;
	fopen_s(&logfile, LOGFILE, "a+");

	if (logfile == NULL)
	{
		return -1;
	}

	fprintf(logfile, "%s\n", logStr);
	fclose(logfile);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值