微信号:cpp_coder

介绍:最专业的C/C++编程学习和程序员发展的综合平台.提供C/C++、汇编语言等、STL、MFC、QT等等学习、数据结构算法思维分析、各领域项目经验分享、资源下载、招聘和资讯的综合服务.

学习如何做Windows服务的程序

2016-03-18 23:39 cpp_coder

相信大家对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; 
}



关注微信号,回复“干货”获取干货下载地址(干货即项目源码哦!)或者登陆个人中心下载
  


 
CPP技术网 更多文章 宏、常量、枚举、结构体和共用体对比分析之常量 宏、常量、枚举、结构体和共用体对比分析之结构体 C/C++声明定义初始化和赋值独家剖析深刻理解 mfc的消息机制,多窗口的互动 MFC中的窗口类:C++类与窗口句柄的结合深入浅出分析
猜您喜欢 黑客入侵网吧 不给钱开不了业 硅谷归来:中国在“互联网夹”,美国已进入“新硬件时代” 基于 fuzz 技术验证移动端 app 的健壮性 基于Docker和Mesos的服务可靠性保障实践 如何成为一个糟糕的程序员