编写ServiceMain函数
下面例子中的MyServiceStart函数是这个服务的ServiceMain函数。MyServiceStart函数可以使用命令行参数,就像控制台程序中main函数那样的方式。第一个参数是传递给服务的值的个数,并且这个个数的最小值总是1。第二个参数是一个字符数组指针。数组的第一项总是当前服务的名称。
MyServiceStart函数首先填充一个SERVICE_STATUS结构,其中包含它所要接受的控制请求代码。虽然这个服务接受SERVICE_CONTROL_PAUSE 和 SERVICE_CONTROL_CONTINUE,但在被要求停止的时候,并没有做什么重要的操作。包含SERVICE_ACCEPT_PAUSE_CONTINUE仅仅是为了举一个例子。如果服务暂停时并没有传递进来的参数,不要支持暂停。
MyServiceStart函数马上调用RegisterServiceCtrlHandler函数,将MyService函数注册成为服务的控制请求处理函数,并且开始作初始化的工作。下面例子中的初始化函数——MyServiceInitialization,只是为了举个例;它没有做任何初始化的工作,比如说创建一个额外的线程。如果服务的初始化工作要花比一秒更长的时间,应该在代码里周期性的调用SetServiceStatus函数建立等待时间和检查点,来指示初始化工作正在进行。
当初始化成功完成时,例子以SERVICE_RUNNING为参数调用SetServiceStatus函数,并且继续它自己的工作。如果在初始化的过程中遇到错误,则以SERVICE_STOPPED为参数调用SetServiceStatus函数,然后返回。
因为例子并没有完成什么真的工作,所以它只是简单的将控制权返回给调用函数。让这个函数自己返回,而不是调用ExitThread函数很重要,因为返回时,可以清理为变量开辟的内存。
#include <windows.h>
SERVICE_STATUS MyServiceStatus;
SERVICE_STATUS_HANDLE MyServiceStatusHandle;
VOID SvcDebugOut(LPSTR String, DWORD Status);
void WINAPI MyServiceStart (DWORD argc, LPTSTR *argv)
{
DWORD status;
DWORD specificError;
MyServiceStatus.dwServiceType = SERVICE_WIN32;
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE;
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwServiceSpecificExitCode = 0;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
MyServiceStatusHandle = RegisterServiceCtrlHandler(
"MyService",
MyServiceCtrlHandler);
if (MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
SvcDebugOut(" [MY_SERVICE] RegisterServiceCtrlHandler
failed %d ", GetLastError());
return;
}
// Initialization code goes here.
status = MyServiceInitialization(argc,argv, &specificError);
// Handle error condition
if (status != NO_ERROR)
{
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
MyServiceStatus.dwWin32ExitCode = status;
MyServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus);
return;
}
// Initialization complete - report running status.
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error
%ld ",status);
}
// This is where the service does its work.
SvcDebugOut(" [MY_SERVICE] Returning the Main Thread ",0);
return;
}
// Stub initialization function.
DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv,
DWORD *specificError)
{
argv;
argc;
specificError;
return(0);
}