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

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

 

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

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

 

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

 

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

 

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

否则无法删除。

 

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

 

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

 

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

 

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

 

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

 

9、不论是否设定SERVICE_INTERACTIVE_PROCESS,在service中都可以通过MessageBox方法弹出MessageBox。这个函数的第一个参数指定为NULL,表示不指定父窗口。在第四个参数中指定MB_DEFAULT_DESKTOP_ONLYMB_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的参数。如果serviceauto-started的,每次开机时就会自动启动,没有给我们手工通过命令行传入参数的机会,这时我们只有在安装service的时候,就把参数传入。在CreateService时,将CreateServicelpBinaryPathName值设成例如SimpleService.exe arg1 arg2的样子,这样每当SCM启动serviceSCM就会从main方法中获得参数并将其传入这个serviceservice_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);

   }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值