分享
 
 
 

NT Service的几个注意点和示例代码

王朝vc·作者佚名  2006-01-30
窄屏简体版  字體: |||超大  

如何编写NT Service在MSDN->Platform SDK->DLLs, Processes, and Threads->Service中说得很清楚了,在这里我就不多说了,这里我就只说一些我个人认为的在编写service过程中要注意的地方。

0、在我们通过控制面板或NET START命令启动一个service时, Service Control Manager (SCM)从注册表里拿到service的可执行程序名,然后运行这个程序,从程序的入口main方法里得到service的service_main方法,然后就进入service_main运行。

一个service程序包含最少包含三个部分,一个是main方法,通常的工作是设置service_main方法和处理命令行参数(例如根据不同的参数执行其他的动作,象安装卸载service,手动启动停止service等等);一个是service_main方法,service程序具体要做的工作就写在这个方法里;一个是ServiceCtrlHandler方法,这个方法在service_main里设置,用来处理由SCM发给service的消息,例如service停止,暂停,系统关机等等。

1、手动启动一个service的方法是在service的main方法里调用StartService,StartService根据service的SERVICE_TABLE_ENTRY将程序转入相应的service_main。启动service时所要作的工作是写在service_main里的。通常的模式是在进入service_main后设状态为SERVICE_START_PENDING,然后进行一些初始化动作,然后执行一个线程或进程,在其中进行service的工作,然后设状态为SERVICE_RUNNING。一定要注意的是,启动service后,必须保证在两分钟内service的状态就会被设成SERVICE_RUNNING,否则会报错。

2、停止一个service的方法是在service的main方法里调用ControlService(hService,SERVICE_CONTROL_STOP,&ServStat)发送SERVICE_CONTROL_STOP消息到Service Control Manager (SCM),SCM收到这个消息后就会通知service,执行ServiceCtrlHandler里case SERVICE_CONTROL_STOP:内的工作。结束动作通常也不能太久,因为在关机时,系统会给每个service大概20秒时间清场(这个时间可以在注册表中设置)

3、安装和卸载一个service的方法是在service的main方法里调用CreateService方法和DeleteService方法,卸载方法前先要判断service是否在运行,如果在运行要先将服务停止

否则无法删除。

4、设置service状态的方法是调用SetServiceStatus,在写service的启动和停止动作是要设置其状态,分别在上面提到的service_main和ServiceCtrlHandler里。查询service状态的方法是QueryServiceStatus,在停止服务时,ControlService方法只是发送了一个消息后就立即返回了,因此通常要在执行完ControlService后,利用while、sleep和QueryServiceStatus来不断查询service的状态,直到状态为SERVICE_STOPPED。StartService与ControlService不同,并不是立即返回的,它会直到service_main内的代码执行完后才返回。

5、service_main即使返回,service的程序进程也不会退出,直到service的状态为SERVICE_STOPPED时,才会终止并退出。

6、在设置service状态时,通过指定dwWin32ExitCode和dwServiceSpecificExitCode可以设定当service在此状态下出错时的弹出式Message。不过只能设定一个错误代码。

7、使用ChangeServiceConfig2添加修改service的描述。

8、默认情况下service程序是不能与桌面交互的,即不能打开窗口。通过ChangeServiceConfig函数设定SERVICE_INTERACTIVE_PROCESS属性,或通过控制面板选中"允许服务与桌面交互",则服务程序可以打开窗口。例如在服务中使用CreateProcess创建了一个进程,只要在STARTUPINFO的wShowWindow和dwFlags设定了SW_SHOW和STARTF_USESHOWWINDOW,则进程就会在打开的一个新窗口中运行。

9、不论是否设定SERVICE_INTERACTIVE_PROCESS,在service中都可以通过MessageBox方法弹出MessageBox。这个函数的第一个参数指定为NULL,表示不指定父窗口。在第四个参数中指定MB_DEFAULT_DESKTOP_ONLY或MB_SERVICE_NOTIFICATION表示以桌面为父窗口。

10.如果要停止的一个Service上有其他正在运行的服务依赖着,这时直接停止这个服务就会出错,因此如果需要停止的服务有可能被其他服务所依赖,在停止前必须用EnumDependentServices()方法取得所有依赖于这个服务的服务,将这些服务依次停止后才行。具体代码示例请看MSDN->HOWTO->ID:Q245230。

11、启动service时可以使用启动参数,在定义service_main方法时其两个参数(DWORD argc, LPTSTR *argv),第一个即为参数个数,第二个则是一个参数数组指针。如何传入参数呢,由于service_main并不是程序入口,因此参数是通过main从命令行传至StartService方法,而调用StartService时,StartService的第二第三个参数,就是传入service_main的参数。如果service是auto-started的,每次开机时就会自动启动,没有给我们手工通过命令行传入参数的机会,这时我们只有在安装service的时候,就把参数传入。在CreateService时,将CreateService的lpBinaryPathName值设成例如SimpleService.exe arg1 arg2的样子,这样每当SCM启动service时SCM就会从main方法中获得参数并将其传入这个service的service_main中。

12.在启动一个service之后,在service的状态是”已启动(SERVICE_RUNNING)”之前,这段时间内,是无法启动另一个service的。

例子代码:

#include

#include

#include

#include

#include

#include

#include

#define SERVICE_NAME "TSService"

#define SERVICE_DISPNAME "vPBX PathFinder TSService"

#define SERVICE_DESCRIPTIONNAME "Start vPBX PathFinder service"

#define SERVICE_EXENAME "\ServiceFrame.exe"

#define LOG_FILENAME "\Service.log"

#define START_EXENAME "\vpbxw.exe"

#define STOP_EXENAME "\StopServer.exe"

#define CMD_EXENAME " -svc"

#define REG_ITEM "SOFTWARE\\VisionNex\\vPBX_Server"

#define REG_KEY "home"

#define FLAG_FILENAME "\PortKeeper.svc"

#define START_DELAY 10000

#define STOP_DELAY 2000

#define COUNT_DELAY 50

#define TIME_DELAY 2000

SERVICE_STATUS m_ServiceStatus;

SERVICE_STATUS_HANDLE m_ServiceStatusHandle;

BOOL bRunning=false;

char Path[256];

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);

void WINAPI ServiceCtrlHandler(DWORD Opcode);

BOOL InstallService(int flag);

BOOL DeleteService();

BOOL StartupService();

BOOL StopService();

BOOL ChangeService();

BOOL EndService();

BOOL QueryReg ();

DWORD GetStatus(SC_HANDLE service);

void LogService(char* error);

BOOL TestTs(int sleep, int count, int sec);

BOOL WaitTsStartup(int sleep, int count, int sec);

int main(int argc, char* argv[])

{

if(!QueryReg()) return 1;

if(argc>1) {

if(strcmp(argv[1],"-i")==0) {

InstallService(0);

}

else if (strcmp(argv[1],"-id")==0){

InstallService(1);

}

else if(strcmp(argv[1],"-d")==0) {

DeleteService();

}

else if(strcmp(argv[1],"-r")==0) {

StartupService();

}

else if(strcmp(argv[1],"-s")==0) {

StopService();

}

else if(strcmp(argv[1],"-c")==0) {

ChangeService();

}

else if(strcmp(argv[1],"-v")==0) {

printf("serivce frame version:1.0.0.5: debug=pipe(limit -0.3)");

}

else {

printf("Unknown Switch Usage\nFor install use -i, for uninstall use -d, for run use -r, for stop use -s\n");

}

}

else {

SERVICE_TABLE_ENTRY DispatchTable[]={{SERVICE_NAME, ServiceMain},{NULL,NULL}};

StartServiceCtrlDispatcher(DispatchTable);

}

return 0;

}

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)

{

DWORD status;

DWORD specificError;

LogService("Service Startup...");

m_ServiceStatus.dwServiceType = SERVICE_WIN32;

m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;

m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;

m_ServiceStatus.dwWin32ExitCode = 0;

m_ServiceStatus.dwServiceSpecificExitCode = 0;

m_ServiceStatus.dwCheckPoint = 0;

m_ServiceStatus.dwWaitHint = 0;

m_ServiceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);

if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) {

LogService("Error: RegisterServiceCtrlHandler");

return;

}

/*

//create pipe

SECURITY_ATTRIBUTES sa;

HANDLE hRead,hWrite;

sa.nLength = sizeof(SECURITY_ATTRIBUTES);

sa.lpSecurityDescriptor = NULL;

sa.bInheritHandle = TRUE;/*

if (!CreatePipe(&hRead,&hWrite,&sa,0)) {

LogService("Error On CreatePipe()");

}

//---------

hWrite = CreateFile("d:\\process.log",GENERIC_WRITE, FILE_SHARE_READ, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

*/

PROCESS_INFORMATION pinfo;

STARTUPINFO sinfo;

ZeroMemory(&sinfo, sizeof(sinfo));

sinfo.cb = sizeof(sinfo);

char strDir[256];

char strDir_stop[256];

strcpy(strDir,Path);

strcpy(strDir_stop,Path);

strcat(strDir,START_EXENAME);

strcat(strDir_stop,STOP_EXENAME);

LPCTSTR lpszBinaryPathName=strDir;

LPCTSTR lpszBinaryPathName_stop=strDir_stop;

LogService("Start Create StopServer process");

if(!CreateProcess(lpszBinaryPathName_stop, CMD_EXENAME, NULL,NULL,FALSE,0,NULL,Path,&sinfo,&pinfo)) {

LogService("Error: CreateProcess:stop befor start");

return;

}

Sleep(STOP_DELAY);

ZeroMemory(&sinfo, sizeof(sinfo));

sinfo.cb = sizeof(sinfo);

//Set Process output

//sinfo.hStdError = hWrite;

//sinfo.hStdOutput = hWrite;

sinfo.wShowWindow = SW_SHOW;

sinfo.dwFlags = STARTF_USESHOWWINDOW ;//| STARTF_USESTDHANDLES;

LogService("Start Create vPBXW process");

if(!CreateProcess(lpszBinaryPathName, CMD_EXENAME, NULL,NULL,TRUE,0,NULL,Path,&sinfo,&pinfo)) {

LogService("Error: CreateProcess:start");

m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;

m_ServiceStatus.dwCheckPoint = 0;

m_ServiceStatus.dwWaitHint = 0;

m_ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;

m_ServiceStatus.dwServiceSpecificExitCode = 0;

SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus);

return;

}

//CloseHandle(hWrite);

LogService("Created vPBXW process");

//read pipe

/*

char buffer[4096] = {0};

DWORD bytesRead = 0;

int i =1;

while (3)

{

i = i -1;

BOOL ret = ReadFile(hRead,buffer,4095,&bytesRead,NULL);

if (ret == NULL){

LogService("Read return NULL");

break;

}

if(ret == 0){

LogService("Read return 0");

break;

}

if(bytesRead == 0){

LogService("Read size 0");

}

else{

LogService("Read Success");

buffer[bytesRead]=0;

LogService(buffer);

}

}

//-----

*/

if(!TestTs(START_DELAY,COUNT_DELAY,TIME_DELAY)){

CloseHandle(pinfo.hThread);

CloseHandle(pinfo.hProcess);

// CloseHandle(hRead);

return;

}

m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;

m_ServiceStatus.dwCheckPoint = 0;

m_ServiceStatus.dwWaitHint = 0;

if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus)) {

LogService("Error: SetServiceStatus:SERVICE_RUNNING");

return;

}

CloseHandle(pinfo.hThread);

CloseHandle(pinfo.hProcess);

//CloseHandle(hRead);

return;

}

BOOL EndService()

{

PROCESS_INFORMATION pinfo;

STARTUPINFO sinfo;

ZeroMemory(&sinfo, sizeof(sinfo));

sinfo.cb = sizeof(sinfo);

char strDir[256];

strcpy(strDir,Path);

strcat(strDir,STOP_EXENAME);

LPCTSTR lpszBinaryPathName=strDir;

if(!CreateProcess(lpszBinaryPathName, CMD_EXENAME, NULL,NULL,FALSE,0,NULL,Path,&sinfo,&pinfo)) {

LogService("Error: CreateProcess:stop");

return false;

}

LogService("Service Stop...");

LogService("Service Stop OK");

CloseHandle(pinfo.hThread);

CloseHandle(pinfo.hProcess);

return true;

}

void WINAPI ServiceCtrlHandler(DWORD Opcode)

{

switch(Opcode)

{

case SERVICE_CONTROL_STOP:

m_ServiceStatus.dwWin32ExitCode = 0;

m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;

m_ServiceStatus.dwCheckPoint = 0;

m_ServiceStatus.dwWaitHint = 0;

SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);

bRunning=false;

EndService();

break;

case SERVICE_CONTROL_SHUTDOWN:

bRunning=false;

EndService();

char strDir[256];

strcpy(strDir,Path);

strcat(strDir,FLAG_FILENAME);

remove(strDir);

break;

case SERVICE_CONTROL_INTERROGATE:

break;

}

return;

}

BOOL InstallService(int flag)

{

HANDLE schSCManager,schService;

schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

if (schSCManager == NULL) {

printf("Error Installing Service\n");

LogService("Error: Installing Service:OpenSCManager");

return false;

}

char strDir[256];

strcpy(strDir,Path);

strcat(strDir,SERVICE_EXENAME);

LPCTSTR lpszBinaryPathName=strDir;

schService = CreateService(schSCManager,

SERVICE_NAME,

SERVICE_DISPNAME,

SERVICE_ALL_ACCESS, // desired access

SERVICE_WIN32_OWN_PROCESS, // service type

SERVICE_AUTO_START, // start type

SERVICE_ERROR_NORMAL, // error control type

lpszBinaryPathName, // 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("Error Installing Service\n");

LogService("Error: Installing Service:CreateService");

CloseServiceHandle(schSCManager);

return false;

}

printf("Service Installed OK\n");

LogService("Service Installed OK");

if(flag == 1){

ChangeServiceConfig(schService,SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL,NULL,NULL,NULL,NULL,NULL);

}

char description[] = SERVICE_DESCRIPTIONNAME;

SERVICE_DESCRIPTION svrDescription;

svrDescription.lpDescription = description;

ChangeServiceConfig2(schService,SERVICE_CONFIG_DESCRIPTION,&svrDescription);

if (!StartService(schService, 0, NULL)) {

printf("Error Start Service\n");

LogService("Error: Start Service:StartService");

}

else{

printf("Service Startup...\n");

WaitTsStartup(START_DELAY,COUNT_DELAY,TIME_DELAY);

}

CloseServiceHandle(schService);

CloseServiceHandle(schSCManager);

return true;

}

BOOL DeleteService()

{

HANDLE schSCManager;

SC_HANDLE hService;

SERVICE_STATUS ServStat;

schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

if (schSCManager == NULL){

printf("Error Uninstalling Service\n");

LogService("Error: Uninstalling Service:OpenSCManager");

return false;

}

hService=OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);

if (hService == NULL) {

printf("Error Uninstalling Service\n");

LogService("Error: Uninstalling Service:OpenService");

CloseServiceHandle(schSCManager);

return false;

}

if(GetStatus(hService) != SERVICE_STOPPED) {

if (!ControlService(hService, SERVICE_CONTROL_STOP, &ServStat)) {

printf("Error Stop Service\n");

LogService("Error: Stop Service:ControlService");

CloseServiceHandle(hService);

CloseServiceHandle(schSCManager);

return false;

}

printf("Service Stop...\n");

LogService("Service Stop...");

Sleep(STOP_DELAY);

printf("Service Stop OK\n");

LogService("Service Stop OK");

}

if(!DeleteService(hService)) {

printf("Error Uninstalling Service\n");

LogService("Error: Uninstalling Service:DeleteService");

CloseServiceHandle(hService);

CloseServiceHandle(schSCManager);

return false;

}

CloseServiceHandle(hService);

CloseServiceHandle(schSCManager);

printf("Service Uninstalled OK\n");

LogService("Service Uninstalled OK");

return true;

}

BOOL ChangeService()

{

HANDLE schSCManager;

SC_HANDLE hService;

schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

if (schSCManager == NULL){

printf("Error Change Service\n");

LogService("Error: Change Service:OpenSCManager");

return false;

}

hService=OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);

if (hService == NULL) {

printf("Error Change Service\n");

LogService("Error: Change Service:OpenService");

CloseServiceHandle(schSCManager);

return false;

}

DWORD dwSize;

LPQUERY_SERVICE_CONFIG lpConfig;

lpConfig = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 1024);

if (!QueryServiceConfig(hService, lpConfig, 1024, &dwSize))

{

CloseServiceHandle(hService);

printf ("Query service config failed!\n");

LogService("Query service config failed!");

return false;

}

if(lpConfig->dwServiceType == SERVICE_WIN32_OWN_PROCESS ){

ChangeServiceConfig(hService,SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL,NULL,NULL,NULL,NULL,NULL);

printf("Service can interact with desktop\n");

LogService("Service can interact with desktop");

}

if(lpConfig->dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS) ){

ChangeServiceConfig(hService,SERVICE_WIN32_OWN_PROCESS , SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL,NULL,NULL,NULL,NULL,NULL);

printf("Service can't interact with desktop\n");

LogService("Service can't interact with desktop");

}

CloseServiceHandle(hService);

CloseServiceHandle(schSCManager);

return true;

}

BOOL StartupService()

{

HANDLE schSCManager;

SC_HANDLE hService;

SERVICE_STATUS ServStat;

schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

if (schSCManager == NULL){

printf("Error Start Service\n");

LogService("Error: Start Service:OpenSCManager");

return false;

}

hService=OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);

if (hService == NULL) {

printf("Error Start Service\n");

LogService("Error: Start Service:OpenService");

CloseServiceHandle(schSCManager);

return false;

}

if(GetStatus(hService) != SERVICE_STOPPED) {

printf("Service already startup\n");

LogService("Error: Service already startup");

CloseServiceHandle(hService);

CloseServiceHandle(schSCManager);

return false;

}

if (!StartService(hService, 0, NULL)) {

printf("Error Start Service\n");

LogService("Error: Start Service:StartService");

}

else{

printf("Service Startup...\n");

WaitTsStartup(START_DELAY,COUNT_DELAY,TIME_DELAY);

}

CloseServiceHandle(hService);

CloseServiceHandle(schSCManager);

return true;

}

BOOL StopService()

{

HANDLE schSCManager;

SC_HANDLE hService;

SERVICE_STATUS ServStat;

schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

if (schSCManager == NULL){

printf("Error stop Service\n");

LogService("Error: stop Service:OpenSCManager");

return false;

}

hService=OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);

if (hService == NULL) {

printf("Error stop Service\n");

LogService("Error: stop Service:OpenService");

CloseServiceHandle(schSCManager);

return false;

}

if(GetStatus(hService) != SERVICE_STOPPED) {

if (!ControlService(hService, SERVICE_CONTROL_STOP, &ServStat)) {

printf("Error Stop Service\n");

LogService("Error: Stop Service:ControlService");

}

else{

printf("Service Stop...\n");

Sleep(STOP_DELAY);

printf("Service Stop OK\n");

}

}

else{

printf("Service already stop\n");

LogService("Error: Service already stop");

}

CloseServiceHandle(hService);

CloseServiceHandle(schSCManager);

return true;

}

DWORD GetStatus(SC_HANDLE service)

{

BOOL SUCCESS;

SERVICE_STATUS status;

DWORD CurrentState;

SUCCESS = QueryServiceStatus(service, &status);

switch(status.dwCurrentState)

{

case SERVICE_RUNNING:

CurrentState = SERVICE_RUNNING;

break;

case SERVICE_STOPPED:

CurrentState = SERVICE_STOPPED;

break;

case SERVICE_PAUSED:

CurrentState = SERVICE_PAUSED;

break;

case SERVICE_CONTINUE_PENDING:

CurrentState = SERVICE_CONTINUE_PENDING;

break;

case SERVICE_PAUSE_PENDING:

CurrentState = SERVICE_PAUSE_PENDING;

break;

case SERVICE_START_PENDING:

CurrentState = SERVICE_START_PENDING;

break;

case SERVICE_STOP_PENDING:

CurrentState = SERVICE_STOP_PENDING;

break;

default:

break;

}

return CurrentState;

}

void LogService(char* error)

{

FILE* fp = NULL;

char strDir[256];

strcpy(strDir,Path);

strcat(strDir,LOG_FILENAME);

LPCTSTR lpszBinaryPathName=strDir;

char* fileName = strDir;

time_t currentTime = time(NULL);

char* cTime = ctime(¤tTime);

fp = fopen(fileName, "a");

fprintf(fp, "%s%s\n\n", cTime, error);

fflush(fp);

fclose(fp);

}

BOOL QueryReg ()

{

BOOL ret = true;

HKEY hKey;

DWORD dwType=REG_SZ;

DWORD dwLength=256;

struct HKEY__*RootKey;

TCHAR *SubKey;

TCHAR *KeyName;

TCHAR *ValueName;

RootKey = HKEY_LOCAL_MACHINE;

SubKey = REG_ITEM;

ValueName= REG_KEY;

if(RegOpenKeyEx(RootKey,SubKey,0,KEY_READ,&hKey)==ERROR_SUCCESS) {

if(RegQueryValueEx(hKey,ValueName,NULL,&dwType,(unsigned char *)Path,&dwLength)!=ERROR_SUCCESS) {

printf("Registry Query Error\n");

LogService("Error: QueryReg:RegQueryValueEx ");

ret = false;

}

RegCloseKey(hKey);

}

else {

printf("Registry Query Error\n");

LogService("Error: OpenReg:RegOpenKeyEx ");

ret = false;

}

return ret;

}

BOOL TestTs(int sleep, int count, int sec)

{

FILE* fp = NULL;

char strDir[256];

strcpy(strDir,Path);

strcat(strDir,FLAG_FILENAME);

LPCTSTR lpszBinaryPathName=strDir;

char* fileName = strDir;

int i = count;

Sleep(sleep);

while(i) {

Sleep(sec);

fp = fopen(fileName, "r");

if(fp != NULL) {

bRunning=true;

LogService("TS Startup OK");

LogService("Service Startup OK");

fclose(fp);

return true;

}

i = i - 1;

}

MessageBox(NULL, "Port 8080 may be in use by another application or service.", "TS Startup failure", MB_DEFAULT_DESKTOP_ONLY);

LogService("Error: TS Startup failure");

m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;

m_ServiceStatus.dwCheckPoint = 0;

m_ServiceStatus.dwWaitHint = 0;

//m_ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;

//m_ServiceStatus.dwServiceSpecificExitCode = 1;

m_ServiceStatus.dwWin32ExitCode = 0;

m_ServiceStatus.dwServiceSpecificExitCode = 0;

SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus);

return false;

}

BOOL WaitTsStartup(int sleep, int count, int sec){

FILE* fp = NULL;

char strDir[256];

strcpy(strDir,Path);

strcat(strDir,FLAG_FILENAME);

LPCTSTR lpszBinaryPathName=strDir;

char* fileName = strDir;

int i = count;

Sleep(sleep);

while(i) {

Sleep(sec);

fp = fopen(fileName, "r");

if(fp != NULL) {

printf("Service Startup OK\n");

fclose(fp);

return true;

}

i = i - 1;

}

printf("Error: Service startup failure: TS startup failure\n");

return false;

}

示例代码:这个例子是MSDN上的,用来停止一个有其他服务依赖的Service。

/*++

Copyright (c) 1998 Microsoft Corporation

Module Name:

threadbased.c

Description:

This sample illustrates how to manage threads in a Windows NT

System Service. To install or remove the service, build the

executable as a Win32 Console Application and use the SC utility

in the Windows NT Resource Kit. See the Simple Service Sample

in the Win32 SDK for sample code to install and remove a service.

The following import libraries are required:

advapi32.lib

user32.lib

Dave McPherson (davemm) 11-March-98

--*/

#include

#include

#include

//

// Global variables.

//

HANDLE hStopEvent;

HANDLE hThreads[3] = {NULL,NULL,NULL};

LPTSTR lpszServiceName;

SERVICE_STATUS_HANDLE ssh;

//

// Function prototypes.

//

DWORD WINAPI ThreadProc(LPVOID lpParameter);

void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv);

void WINAPI Service_Ctrl(DWORD dwCtrlCode);

void ErrorStopService(LPTSTR lpszAPI);

void SetTheServiceStatus(DWORD dwCurrentState,DWORD dwWin32ExitCode,

DWORD dwCheckPoint, DWORD dwWaitHint);

//

// _tmain - Entry point for service. Calls StartServiceCtrlDispatcher

// and then blocks until the ServiceMain function returns.

//

void _tmain(int argc, TCHAR *argv[])

{

SERVICE_TABLE_ENTRY ste[] =

{{TEXT(""),(LPSERVICE_MAIN_FUNCTION)Service_Main},{NULL, NULL}};

OutputDebugString(TEXT("Entered service code\n"));

if (!StartServiceCtrlDispatcher(ste))

{

TCHAR error[256];

wsprintf(error,

TEXT("Error code for StartServiceCtrlDispatcher: %u.\n"),

GetLastError());

OutputDebugString(error);

}

else

OutputDebugString(TEXT("StartServiceCtrlDispatcher returned!\n"));

}

//

// Service_Main - This is called by the service control manager after

// the call to StartServiceCtrlDispatcher.

//

void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)

{

DWORD ThreadId;

DWORD t;

DWORD dwWaitRes;

// Obtain the name of the service.

lpszServiceName = lpszArgv[0];

// Register the service ctrl handler.

ssh = RegisterServiceCtrlHandler(lpszServiceName,

(LPHANDLER_FUNCTION)Service_Ctrl);

// Create the event to signal the service to stop.

hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

if (hStopEvent == NULL)

ErrorStopService(TEXT("CreateEvent"));

/*******************************************************************/

// This is where you can put one-time work that you want to complete

// before starting.

for (t=0;t<3;t++)

{

hThreads[t] = CreateThread(NULL,0,ThreadProc,

(LPVOID)t,0,&ThreadId);

if (hThreads[t] == INVALID_HANDLE_VALUE)

ErrorStopService(TEXT("CreateThread"));

}

/*******************************************************************/

// The service has started.

SetTheServiceStatus(SERVICE_RUNNING, 0, 0, 0);

OutputDebugString(TEXT("SetTheServiceStatus, SERVICE_RUNNING\n"));

//

// Main loop for the service. <-----------------------------

//

while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0){

/***************************************************************/

// Main loop for service.

/***************************************************************/

}

// Now wait for threads to exit.

for (t=1;TRUE;t++)

{

if ((dwWaitRes = WaitForMultipleObjects(3,hThreads,TRUE,1000))

== WAIT_OBJECT_0)

break;

else if((dwWaitRes == WAIT_FAILED)||(dwWaitRes==WAIT_ABANDONED))

ErrorStopService(TEXT("WaitForMultipleObjects"));

else

SetTheServiceStatus(SERVICE_STOP_PENDING, 0, t, 3000);

}

// close the event handle and the thread handle

if (!CloseHandle(hStopEvent))

ErrorStopService(TEXT("CloseHandle"));

if (!CloseHandle(hThreads[0]))

ErrorStopService(TEXT("CloseHandle"));

if (!CloseHandle(hThreads[1]))

ErrorStopService(TEXT("CloseHandle"));

if (!CloseHandle(hThreads[2]))

ErrorStopService(TEXT("CloseHandle"));

// Stop the service.

OutputDebugString(TEXT("SetTheServiceStatus, SERVICE_STOPPED\n"));

SetTheServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0);

}

//

// Service_Ctrl - Where control signals from the Service Control Mgr

// are handled.

//

void WINAPI Service_Ctrl(DWORD dwCtrlCode)

{

DWORD dwState = SERVICE_RUNNING;

switch(dwCtrlCode)

{

case SERVICE_CONTROL_STOP:

dwState = SERVICE_STOP_PENDING;

break;

case SERVICE_CONTROL_SHUTDOWN:

dwState = SERVICE_STOP_PENDING;

break;

case SERVICE_CONTROL_INTERROGATE:

break;

default:

break;

}

// Set the status of the service.

SetTheServiceStatus(dwState, NO_ERROR, 0, 0);

OutputDebugString(

TEXT("SetTheServiceStatus, Service_Ctrl function\n"));

// Tell service_main thread to stop.

if ((dwCtrlCode == SERVICE_CONTROL_STOP) ||

(dwCtrlCode == SERVICE_CONTROL_SHUTDOWN))

{

if (!SetEvent(hStopEvent))

ErrorStopService(TEXT("SetEvent"));

else

OutputDebugString(TEXT("Signal service_main thread\n"));

}

}

//

// ThreadProc - Thread procedure for all three worker threads.

//

DWORD WINAPI ThreadProc(LPVOID lpParameter)

{

INT nThreadNum = (INT)lpParameter;

TCHAR szOutput[25];

while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0)

{

// Just to have something to do, it will beep every second.

Sleep(1000);

wsprintf(szOutput,TEXT("\nThread %d says Beep\n"),nThreadNum);

OutputDebugString(szOutput); //Send visual to debugger.

}

return 0;

}

//

// SetTheServiceStatus - This just wraps up SetServiceStatus.

//

void SetTheServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,

DWORD dwCheckPoint, DWORD dwWaitHint)

{

SERVICE_STATUS ss; // Current status of the service.

//

// Disable control requests until the service is started.

//

if (dwCurrentState == SERVICE_START_PENDING)

ss.dwControlsAccepted = 0;

else

ss.dwControlsAccepted =

SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;

// Other flags include SERVICE_ACCEPT_PAUSE_CONTINUE

// and SERVICE_ACCEPT_SHUTDOWN.

// Initialize ss structure.

ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;

ss.dwServiceSpecificExitCode = 0;

ss.dwCurrentState = dwCurrentState;

ss.dwWin32ExitCode = dwWin32ExitCode;

ss.dwCheckPoint = dwCheckPoint;

ss.dwWaitHint = dwWaitHint;

// Send status of the service to the Service Controller.

if (!SetServiceStatus(ssh, &ss))

ErrorStopService(TEXT("SetServiceStatus"));

}

//

// ErrorStopService - Use this when there is an API error or bad

// situation this just ends the service and

// displays an error message to the debugger.

//

void ErrorStopService(LPTSTR lpszAPI)

{

INT t;

TCHAR buffer[256] = TEXT("");

TCHAR error[1024] = TEXT("");

LPVOID lpvMessageBuffer;

DWORD dwWaitRes;

wsprintf(buffer,TEXT("API = %s, "), lpszAPI);

lstrcat(error, buffer);

ZeroMemory(buffer, sizeof(buffer));

wsprintf(buffer,TEXT("error code = %d, "), GetLastError());

lstrcat(error, buffer);

// Obtain the error string.

FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,

NULL, GetLastError(),

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

(LPTSTR)&lpvMessageBuffer, 0, NULL);

ZeroMemory((LPVOID)buffer, (DWORD)sizeof(buffer));

wsprintf(buffer,TEXT("message = %s"), (TCHAR *)lpvMessageBuffer);

lstrcat(error, buffer);

// Free the buffer allocated by the system.

LocalFree(lpvMessageBuffer);

// Write the error string to the debugger.

OutputDebugString(error);

// If you have threads running, tell them to stop. Something went

// wrong, and you need to stop them so you can inform the SCM.

SetEvent(hStopEvent);

// Wait for the threads to stop.

for (t=1;TRUE;t++)

{

if ((dwWaitRes = WaitForMultipleObjects(3,hThreads,TRUE,1000))

== WAIT_OBJECT_0)

break;

else if ((dwWaitRes== WAIT_FAILED)||(dwWaitRes== WAIT_ABANDONED))

break; // Our wait failed

else

{

SetTheServiceStatus(SERVICE_STOP_PENDING, 0, t, 3000);

}

}

// Stop the service.

SetTheServiceStatus(SERVICE_STOPPED, GetLastError(), 0, 0);

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有