VC编写系统服务程序笔记

转载自:http://blog.csdn.net/pgshow/article/details/7677583


[cpp]  view plain copy
  1. 这里我要把自己写好的程序设置为开机启动了,所以注册为服务程序是最好的方法,先看VC写服务程序的思路  

 

服务程序通常编写成控制台类型的应用程序,总的来说,一个遵守服务控制管理程序接口要求的程序包含下面三个函数:

  1.服务程序主函数(main):调用系统函数 StartServiceCtrlDispatcher 连接程序主线程到服务控制管理程序

  StartServiceCtrlDispatcher 函数有一个 SERVICE_TABLE_ENTRY 作为参数,里面指定了 Service 的名字和入口点。 如果 StartServiceCtrlDispatcher 函数调用成功,被调用线程不会在 Service 进程结束以前返回。

  SERVICE_TABLE_ENTRY 结构具体描述如下:

[cpp]  view plain copy
  1. typedef struct _SERVICE_TABLE_ENTRY {  
  2.     LPTSTR lpServiceName;  //一个以 NULL 结尾的字符串,标识服务名,如果是 SERVICE_WIN32_OWN_PROCESS 类型的服务,这个字符串会被忽略  
  3.     LPSERVICE_MAIN_FUNCTION lpServiceProc;  //指向服务入口点函数  
  4. } SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;   

 

  2.服务入口点函数(ServiceMain):执行服务初始化任务,同时执行多个服务的服务进程有多个服务入口函数
  

  标准的ServiceMain 函数需要执行以下任务:

  1.马上调用 RegisterServiceCtrlHandlerEx 去注册一个 处理函数(HandlerEx) 去处理 Service 的 控制要求。返回值是通知 SCM 的 Service 状态处理的 Handle

  2.执行初始化单元,如果初始化代码的执行时间少于1秒或很短,可以在 ServiceMain 里执行,如果 初始化时间很长,最好先调用 SetServiceStatus 函数,指定状态为 SERVICE_START_PENDING (启动中)。

  如果初始化时间超过30秒,就必须建立另外的线程完成这些共同的初始化工作,从而保证服务程序主函数能及时地调用 StartServiceCtrlDispatcher 函数

  如果 初始化 或 运行 过程中出现了错误,应该调用 SetServiceStatus 并指定 SERVICE_STOP_PENDING(正在停止) 。完成清场工作后,再指定现在状态为 SERVICE_STOPPED, 记得在 SERVICE_STATUS 结构中指定成员 dwServiceSpecificExitCode 和 dwWin32ExitCode 的值,用来指定错误的类型。

  3.控制服务处理程序函数(Handler):在服务程序收到控制请求时由控制分发线程引用。

  当SCM发出控制请求的时候,控制处理函数必须在30秒内返回,否则 SCM 会返回错误。

 

好了,思路有了,下面是每个步骤详细的写法,这里有现成的说明我就不自己写了:http://www.vckbase.com/index.php/wv/1193

另附服务应用程序详细介绍:http://blog.csdn.net/showna/article/details/1543517

 

我写的源码,东拼西凑的,不对的地方希望能指出啊:

 

[cpp]  view plain copy
  1. // Services_test.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "Windows.h"  
  6.   
  7. //全局变量  
  8. SERVICE_STATUS         MyServiceStatus;  
  9. SERVICE_STATUS_HANDLE  MyServiceStatusHandle;  
  10. TCHAR szServiceName[] = TEXT("ServiceTest");  
  11. DWORD i = 0;  
  12.   
  13. //向前声明  
  14. void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);  //服务主函数  
  15. void WINAPI ControlHandler(DWORD dwMsg);            //服务控制函数  
  16. int  InitService();                                 //服务初始化函数  
  17.   
  18. int _tmain(int argc, _TCHAR* argv[])  
  19. {  
  20.     //初始化一个分配表  
  21.     SERVICE_TABLE_ENTRY ServiceTable[] =  
  22.     {  
  23.         { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },  
  24.         { NULL, NULL } //分派表的最后一项必须是服务名和服务主函数域的 NULL 指针,所以这两项为NULL  
  25.     };  
  26.   
  27.     if(!StartServiceCtrlDispatcher(ServiceTable))  // 启动服务的控制分派机线程  
  28.     {  
  29.         OutputDebugString(TEXT("分派机启动服务失败!"));  
  30.     }  
  31.     return 0;  
  32. }  
  33.   
  34. void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)   
  35. {  
  36.     int error;  
  37.   
  38.     //指定服务特征和其当前状态  
  39.     MyServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;  //服务类型  
  40.     MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;     //指定服务的当前状态  
  41.     MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;   //这个成员表示哪些控制通执服务是可接受的  
  42.     MyServiceStatus.dwWin32ExitCode = 0;                        //这两个域在你终止服务并报告退出细节时很有用。  
  43.     MyServiceStatus.dwServiceSpecificExitCode = 0;              //初始化服务时并不退出,因此,它们的值为0  
  44.     MyServiceStatus.dwCheckPoint = 0;                           //这二个成员允许  
  45.     MyServiceStatus.dwWaitHint = 0;                             //一个服务回报它的进度  
  46.   
  47.     //注册服务控制  
  48.     MyServiceStatusHandle = RegisterServiceCtrlHandler(szServiceName, ControlHandler);   
  49.   
  50.     if (NULL == MyServiceStatusHandle)  
  51.     {  
  52.         //注册失败就返回  
  53.         OutputDebugString(TEXT("注册服务失败!"));  
  54.         return;   
  55.     }  
  56.   
  57.     error = InitService(); //初始化数据  
  58.   
  59.     if (error)   
  60.     {  
  61.         // 初始化失败,终止服务  
  62.         MyServiceStatus.dwCurrentState = SERVICE_STOPPED;   
  63.         MyServiceStatus.dwWin32ExitCode = -1;   
  64.         SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus); //向 SCM 报告服务的状态  
  65.         return// 退出 ServiceMain  
  66.     }  
  67.   
  68.     // 如果初始化成功,向 SCM 报告运行状态   
  69.     MyServiceStatus.dwCurrentState = SERVICE_RUNNING;   
  70.     SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus);  
  71.   
  72.     while (MyServiceStatus.dwCurrentState == SERVICE_RUNNING)  
  73.     {  
  74.         //这里放你要实现的功能函数  
  75.   
  76.         if(i != 100)  
  77.             return;  
  78.   
  79.         MessageBeep(0);  
  80.         Sleep(3000);  
  81.     }  
  82.   
  83.     return;   
  84.   
  85. }   
  86.   
  87. int InitService()  
  88. {  
  89.     //获取系统目录地址,失败就返回-1  
  90.     i = 100;  
  91.     return 0;  
  92. }  
  93.   
  94. void WINAPI ControlHandler(DWORD dwMsg)   
  95. {   
  96.    switch(dwMsg)   
  97.    {  
  98.    case SERVICE_CONTROL_STOP:   
  99.        //响应停止服务控制  
  100.        MyServiceStatus.dwWin32ExitCode = 0;   
  101.        MyServiceStatus.dwCurrentState = SERVICE_STOPPED;   
  102.        SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus);  
  103.        return;   
  104.   
  105.    default:  
  106.        break;  
  107.     }   
  108.     //向 SCM 报告服务的状态  
  109.     SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus);  
  110.     return;   
  111. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值