当前位置:C++技术网 > 资讯 > 学习如何做Windows服务的程序

学习如何做Windows服务的程序

更新时间:2016-03-17 12:04:15浏览次数:1+次

  相信大家对Windows的服务并不陌生,但Windows的服务是怎么运作和创建的,我来讲讲我自己对Windows服务程序的理解。

  首先来了解一下Windows的SC命令,这个命令是用来创建,修改和删除Windows服务,调用不同的参数来控制Windows服务,更详细的信息可以通过搜索引擎查询,也可以查阅相关书籍。

  为了让自己对如何生成Windows服务程序的逻辑更加清晰,画出了简单的逻辑图,如下图所示

  

  源码在文章最底部,SC创建服务需要绑定运行程序所在的文件目录,否则服务不知道去哪里找要运行的程序,运行程序要做的事情有两件,一是开启线程来监听服务控制器里对应的服务,二是运行真正要做事的代码。

  调用StartServiceCtrlDispatcher函数来创建监听的线程ServiceMain,在ServiceMain函数里调用RegisterServiceCtrlHandler来创建监听器即ControlHandler来监听服务控制器里对应的服务,如果用户将服务开启,ControlHandler函数就会接受到该动作对应的参数,执行对应的操作即停止运行程序,即图中“真正要用到的代码”。

  SetServiceStatus函数是用来更新服务控制管理器调用服务的状态信息,当用户开启服务时,会开始运行图中的流程,并调用SetServiceStatus来改变服务的状态,即状态列显示“已启动”。

  最后在ServiceMain里运行真正要用的代码,这样就开始服务的人生了。

  其实我一开始的本意不是这样的,我一开始是打算弄一个程序出来,运行该程序就自动创建服务并开启,这样就不用SC命令,更加独立化。

  我正在研究这个,如果做出来了继续发布文章分享给大家,如果大家有什么意见或者建议,欢迎留言,如果你也对Windows的服务感兴趣,欢迎来写文章分享,共同进步。

#include <windows.h>
#include <stdio.h>

#define SLEEP_TIME 5000
#define LOGFILE "C:/MyServices/memstatus.txt"


SERVICE_STATUS ServiceStatus; 
SERVICE_STATUS_HANDLE hStatus; 

void ServiceMain(int argc, char** argv); 
void ControlHandler(DWORD request); 
int InitService();
int WriteToLog(char* str);


int main(int argc, char* argv[])
{
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = "MemoryStatus";
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;

    // 启动服务的控制分派机线程
    StartServiceCtrlDispatcher(ServiceTable); 
}




void ServiceMain(int argc, char** argv) 
{ 
   int error; 
 
   ServiceStatus.dwServiceType = 
      SERVICE_WIN32; 
   ServiceStatus.dwCurrentState = 
      SERVICE_START_PENDING; 
   ServiceStatus.dwControlsAccepted   =  
      SERVICE_ACCEPT_STOP | 
      SERVICE_ACCEPT_SHUTDOWN;
   ServiceStatus.dwWin32ExitCode = 0; 
   ServiceStatus.dwServiceSpecificExitCode = 0; 
   ServiceStatus.dwCheckPoint = 0; 
   ServiceStatus.dwWaitHint = 0; 
 
   hStatus = RegisterServiceCtrlHandler(
      "MemoryStatus", 
      (LPHANDLER_FUNCTION)ControlHandler); 
   if (hStatus == (SERVICE_STATUS_HANDLE)0) 
   { 
      // Registering Control Handler failed
      return; 
   }  
   // Initialize Service 
   error = InitService(); 
   if (!error) 
   {
      // Initialization failed
      ServiceStatus.dwCurrentState = 
         SERVICE_STOPPED; 
      ServiceStatus.dwWin32ExitCode = -1; 
      SetServiceStatus(hStatus, &ServiceStatus); 
      return; 
   } 
   // We report the running status to SCM. 
   ServiceStatus.dwCurrentState = 
      SERVICE_RUNNING; 
   SetServiceStatus (hStatus, &ServiceStatus);
 
   MEMORYSTATUS memory;
   // The worker loop of a service
   while (ServiceStatus.dwCurrentState == 
          SERVICE_RUNNING)
   {
      char buffer[16];
      GlobalMemoryStatus(&memory);
      sprintf(buffer, "%d", memory.dwAvailPhys);
      int result = WriteToLog(buffer);
      if (result)
      {
         ServiceStatus.dwCurrentState = 
            SERVICE_STOPPED; 
         ServiceStatus.dwWin32ExitCode      = -1; 
         SetServiceStatus(hStatus, 
                          &ServiceStatus);
         return;
      }
      Sleep(SLEEP_TIME);
   }
   return; 
}



void ControlHandler(DWORD request) 
{ 
   switch(request) 
   { 
      case SERVICE_CONTROL_STOP: 
         WriteToLog("Monitoring stopped.");

         ServiceStatus.dwWin32ExitCode = 0; 
         ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
         SetServiceStatus (hStatus, &ServiceStatus);
         return; 
 
      case SERVICE_CONTROL_SHUTDOWN: 
         WriteToLog("Monitoring stopped.");

         ServiceStatus.dwWin32ExitCode = 0; 
         ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
         SetServiceStatus (hStatus, &ServiceStatus);
         return; 
        
      default:
         break;
    } 
 
    // Report current status
    SetServiceStatus (hStatus, &ServiceStatus);
 
    return; 
}


int WriteToLog(char* str)
{
    FILE* log;
    log = fopen(LOGFILE, "a+");
    if (log == NULL)
    return -1;
    fprintf(log, "%s ", str);
    fclose(log);
    return 0;
}

int InitService(){
    WriteToLog("Monitoring started.");
    return true;
}