Windows Service

摘要:
5.1设置服务门户参数和注册控制命令ServiceStatus dwServiceType=Service_ WIN32;服务状态。dwCurrentState=服务_启动_待定;服务状态。dwControlsAccepted=服务_接受_停止|服务_接受/关闭;服务状态。dwWin32ExitCode=0;服务状态。dwServiceSpecificExitCode=0;服务状态。dwCheckPoint=0;服务状态。dwWaitHint=0;hStatus=RegisterServiceCtrlHandler;如果{//RegisteringControlHandlerfiled return;}DwServiceType:指示服务类型并创建Win32服务。分配SERVICE_ WIN32DwCurrentState:指定服务的当前状态。第三步将讨论处理控制请求;DwWin32ExitCode和dwServiceSpecificExitCode:当您终止服务并报告退出详细信息时,这两个域非常有用。ServiceMain应尽早注册服务的控制处理器。

  Windows Service是一种在后台运行的程序,它没有与用户交互的界面操作.

  Windows Service属于控制台程序,下面将对Service编程做一个简要的介绍:

  1.包含头文件

    #include<stdio.h>  日志写入磁盘

  2.输入日志路径 

    #define SERVICE_LOG_FILE   ("D:\\feAudioService\\AudioService\\log.txt")

  3.静态全局变量

    static SERVICE_STATUS ServiceStatus;
    static SERVICE_STATUS_HANDLE hStatus;

    static FILE* log;


 

    现在可以编码了,服务程序控制台程序的一个子集。因此,需要定义 main 函数,它是程序的入口点。

  4.控制台程序入口

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

     ServiceTable[1].lpServiceName = NULL;
     ServiceTable[1].lpServiceProc = NULL;


     // Start the control dispatcher thread for our service
     StartServiceCtrlDispatcher(ServiceTable);
  }

  5.服务入口点

  void ServiceMain(int argc, const char **argv){}

  在服务入口里面,需要设置服务入口的参数和注册命令控制器、打开和写入日志,以及报告服务运行状态。

    5.1 设置服务入口参数和注册控制命令

     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( "PlayAudioService", (LPHANDLER_FUNCTION)ControlHandler); 
     if (hStatus == (SERVICE_STATUS_HANDLE)0) 
     { 
        // Registering Control Handler failed
        return ; 
     } 

     dwServiceType:指示服务类型,创建 Win32 服务。赋值 SERVICE_WIN32;

     dwCurrentState:指定服务的当前状态。因为服务的初始化在这里没有完成,所以这里的状态为 SERVICE_START_PENDING;

     dwControlsAccepted:这个域通知 SCM 服务接受哪个域。本文例子是允许 STOP 和 SHUTDOWN 请求。处理控制请求将在第三步讨论;

     dwWin32ExitCode 和 dwServiceSpecificExitCode:这两个域在你终止服务并报告退出细节时很有用。初始化服务时并不退出,因此,它们的值为 0;

     dwCheckPoint 和 dwWaitHint:这两个域表示初始化某个服务进程时要30秒以上。本文例子服务的初始化过程很短,所以这两个域的值都为 0。

        ServiceMain 应该尽可能早早为服务注册控制处理器。这要通过调用 RegisterServiceCtrlHadler 函数来实现。你要将两个参数传递给此函数:

    服务名和指向ControlHandlerfunction 的指针。

    5.2 日志相关操作

    void OpenLog()
    {
      log = fopen(SERVICE_LOG_FILE, "a+");
    }

    void WriteToLog(char* str)
    {
      OpenLog();

      fprintf(log, "%s\n", str);
      CloseLog();
    }

    void CloseLog()
    {
      fclose(log);
    }

     5.3 报告服务运行状态

      // We report the running status to SCM. 
     ServiceStatus.dwCurrentState = SERVICE_RUNNING; 
     SetServiceStatus (hStatus, &ServiceStatus);

     注册完控制处理器之后,获得状态句柄(hStatus);通过调用 SetServiceStatus 函数,用 hStatus 向 SCM 报告服务的状态。

  6.命令控制器
  void ControlHandler(DWORD request)
  {

    switch(request) 
    {
      case SERVICE_CONTROL_STOP: 

        WriteToLog("Service Stop Exiting\n");

        done = 1;
        Mux_ExitMuxApp();
        WriteToLog("Service Stop Exit OK\n");

        ServiceStatus.dwWin32ExitCode = 0; 
        ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
        SetServiceStatus (hStatus, &ServiceStatus);

      return; 
 
      case SERVICE_CONTROL_SHUTDOWN:  
        WriteToLog("Service Shutdown Exiting\n");

        done = 1;
        Mux_ExitMuxApp();
        WriteToLog("Service Shutdown Exit OK\n");

        ServiceStatus.dwWin32ExitCode = 0; 
        ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
        SetServiceStatus (hStatus, &ServiceStatus);

      return; 
        
      default:
        break;
    } 
    // Report current status
    SetServiceStatus (hStatus, &ServiceStatus);

  }

  7.异常处理

  void  ServiceError(void)
  {
    ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
    ServiceStatus.dwWin32ExitCode = -1; 
    SetServiceStatus(hStatus, &ServiceStatus);
  }

  8.安装和卸载

  在DOS下输入命令:

  安装: sc create PlayAudioService binPath= D:\feAudioService\AudioService\Debug\AudioService.exe

  卸载: sc delete PlayAudioService

   

  相关文章:http://blog.chinaunix.net/u1/51827/showart_1986489.html

免责声明:文章转载自《Windows Service》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Delphi中TxmlDocument控件的用法 转EasyUI treegrid 获取编辑状态中某字段的值 [getEditor方法获取不到editor]下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

微信小程序 webview直接关闭所有回到小程序

解决方案:通过微信浏览器监控返回键和H5跳转小程序。...

微信小程序中使用Vant Weapp的ActionSheet上拉菜单出现的样式问题

以下修改的源码均在action-sheet组件中。在index.wxss:2.下方的取消按钮不居中,通过审查元素发现它的宽带已经超出了手机屏幕的宽度,出现的滚动条导致的,具体什么原因导致暂时不知,解决方案是给.van-action-sheet__cancel添加样式box-sizing:border-box可解决。在index.wxss:.van-actio...

RedisTemplate

在SpringBoot@RequestMapping(“/del/{key}”)publicStringdel(@PathVariable(“key”)Stringkey){try{//当该键不存在时,异常redisTemplate.delete(key);return“Success”;}将不会引发catch(Exceptione){returne.get...

Innodb_large_prefix

但是,索引列的总长度不能超过3072字节的限制仍然存在...

ORACLE无法删除当前连接用户

今天在做Oracle数据库是遇到ORACLE无法删除当前连接用户,经查找可用如下方法解决。SQL˃dropuseracascade;//删除用户以及用户表空间下所有对象用户已丢弃。...

NFC应用于公交卡

由于历史遗留,NFC的兼容性实在太差。一个完备的NFC产品,应该包括三个部分:NFC硬件、统一的系统接口支持、App。这种情况下,手机NFC相当于公交公司的读卡和写卡器。...