用C/C++创建windows服务程序

来源:互联网 发布:mac字体下载ttf 编辑:程序博客网 时间:2024/05/13 11:53

一、演示过程

下方代码演示了如何使用vs(C/C++)创建windows服务程序

工程文件下载地址:  http://download.csdn.net/download/sooth2008/2759082

使用visual studio创建一个win32控制台应用程序,编译后就OK了。

然后开始->运行->cmd->回车,输入 sc create test binPath= 编译成功后的可执行文件的路径回车就创建了一个服务.

注意这里的格式,“=”后面是必须空一格的,否则会出现错误。  

然后开始->运行->services.msc->回车就可以看到刚刚创建的服务了。

描述: 
        SC 是用于与服务控制管理器和服务进行通信的命令行程序。 
用法: 
        sc <server> [command] [service name] <option1> <option2>...

        选项 <server> 的格式为 "\\ServerName" 
        键入 "sc [command]" 可以获得有关命令的进一步帮助 
        命令: 
          query-----------查询服务的状态, 
                          或枚举服务类型的状态。 
          queryex---------查询服务的扩展状态, 
                          或枚举服务类型的状态。 
          start-----------启动服务。 
          pause-----------向服务发送 PAUSE 控制请求。 
          interrogate-----向服务发送 INTERROGATE 控制请求。 
          continue--------向服务发送 CONTINUE 控制请求。 
          stop------------向服务发送 STOP 请求。 
          config----------更改服务的配置(永久)。 
          description-----更改服务的描述。 
          failure---------更改服务失败时执行的操作。 
          failureflag-----更改服务的失败操作标志。 
          sidtype---------更改服务的服务 SID 类型。 
          privs-----------更改服务的所需权限。 
          qc--------------查询服务的配置信息。 
          qdescription----查询服务的描述。 
          qfailure--------查询失败时服务执行的操作。 
          qfailureflag----查询服务的失败操作标志。 
          qsidtype--------查询服务的服务 SID 类型。 
          qprivs----------查询服务的所需权限。 
          delete----------(从注册表)删除服务。 
          create----------创建服务(将其添加到注册表)。 
          control---------向服务发送控制。 
          sdshow----------显示服务的安全描述符。 
          sdset-----------设置服务的安全描述符。 
          showsid---------显示相应于假定名称的 SID 字符串。 
          GetDisplayName--获取服务的 DisplayName。 
          GetKeyName------获取服务的 ServiceKeyName。 
          EnumDepend------枚举服务的依存关系。 
示例: 
        sc start MyService 
---------------------------------- 
    实际上sc所完成的功能就是“控制面板.管理工具”中看到的“服务”完成的功能。 
在命令行中输入下面的命令,可以看到详细语法: 
---------------------------------- 
sc config hlep 
---------------------------------- 
sc config 服务名 start= AUTO    (自动) 
sc config 服务名 start= DEMAND  (手动) 
sc config 服务名 start= DISABLED(禁用) 
    注意:等号后面必须有一个空格。

 

1、启动服务:

右键点击->启动 大功告成。(或者在提示建立成功后,可以直接输入“net start Test” 来启动服务)

此时可以在任务栏管理器中看到这个exe在运行。

PS:该服务每隔5秒往d:/test.txt 写入一条记录你的代码就应该加在srv_core_thread中,当然你也可以添加多个类似srv_core_thread的线程.

在服务停止时我们可以看到D:\下生成了test.txt文档

 

 

      
 
异常情况:假如启动服务时提示
 
这是因为运行作为服务的应用程序不是按服务的流程写的。所以运行提示“服务没有及时响应启动或控制请求
 2、停止服务

 

3、删除服务 :

在 "开始->运行->cmd" 中输入 sc delete TEST

此时虽然把服务删除了,但是从->services.msc->还是可以看到test服务的状态不审“已经启动".

任务栏管理器上还是有此进程的存在。

 

4、

这样在开机会会自动启动此服务,经实验,在XP开机弹出登陆框时,服务已经启动了

问题:何时加载这些服务?

答: 请参照我的文章:<<Winlogon、LSASS、Userinit>>

里面有这样一句“winlogon创建服务控制管理器(SCM)进程(\windows\system32\Services.exe),而SCM进程又依次加载所有被标记为自动-启动斩服务和设备驱动程序”。

5、在服务启动时弹出窗口

[cpp] view plaincopy
  1. void WINAPI service_main(int argc, char** argv)   
  2. {         
  3.     ServiceStatus.dwServiceType        = SERVICE_WIN32;   
  4.     ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;   
  5.     ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;   
  6.     ServiceStatus.dwWin32ExitCode      = 0;   
  7.     ServiceStatus.dwServiceSpecificExitCode = 0;   
  8.     ServiceStatus.dwCheckPoint         = 0;   
  9.     ServiceStatus.dwWaitHint           = 0;    
  10.     hServiceStatusHandle = RegisterServiceCtrlHandler(_T(SERVICE_NAME), ServiceHandler);   
  11.     if (hServiceStatusHandle==0)   
  12.     {  
  13.         DWORD nError = GetLastError();  
  14.     }    
  15.     ::MessageBox(NULL, L"Service test start Ok", L"OK", MB_OK);  


运行时出现提示:

6、脚本启动服务

 打开一个Txt,写上下面的内容,保存“服务名.bat”文

:启动服务名

echo 启动服务名

net start 服务名

pause

 

关闭也一样(打开一个Txt,写上下面的内容,保存“服务名.bat”文件):

:关闭服务名

echo 关闭服务名

net stop 服务名

pause

 

[plain] view plaincopy
  1. @echo off  
  2.   
  3. sc.exe create test type= own type= interact start= auto binPath= %CD%\test.exe  


 

 

 二、代码

1、不加服务事件

[cpp] view plaincopy
  1. /******************************************************************************* 
  2. Written by:   shiyang sun 
  3.     First: you can used this code free,absolutely free! 
  4.     Second:of course,you can remove this header unconstrained! 
  5.     but this header might useful if you sometimes want to kick my ass or praise me. 
  6.  
  7.    Copyright:none 
  8.    Get more message on:http://blog.sina.com.cn/lipfreedom 
  9.    Address:sunshiyang shenzhen city guangdong province china 
  10.    E-mail:zyy6569@163.com 
  11.  
  12.  Create date:2010/10/14 
  13. ********************************************************************************/  
  14.   
  15. #include "stdafx.h"  
  16. #include "Windows.h"  
  17.   
  18. #define SERVICE_NAME "srv_demo"  
  19.   
  20. SERVICE_STATUS ServiceStatus;  
  21. SERVICE_STATUS_HANDLE hServiceStatusHandle;  
  22. void WINAPI service_main(int argc, char** argv);   
  23. void WINAPI ServiceHandler(DWORD fdwControl);  
  24.   
  25. TCHAR szSvcName[80];  
  26. SC_HANDLE schSCManager;  
  27. SC_HANDLE schService;  
  28. int uaquit;  
  29. FILE* log;  
  30.   
  31. DWORD WINAPI srv_core_thread(LPVOID para)  
  32. {     
  33. int i = 0;  
  34. for(;;)  
  35. {  
  36.     if(uaquit)  
  37.     {  
  38.         break;   
  39.     }  
  40.     fprintf(log,"srv_core_thread run time count:%d\n",i++);  
  41.     Sleep(5000);   
  42. }      
  43.    return NULL;   
  44. }     
  45.   
  46.   
  47. void WINAPI ServiceHandler(DWORD fdwControl)  
  48. {  
  49.     switch(fdwControl)   
  50.     {  
  51.         case SERVICE_CONTROL_STOP:  
  52.         case SERVICE_CONTROL_SHUTDOWN:  
  53.         ServiceStatus.dwWin32ExitCode = 0;   
  54.         ServiceStatus.dwCurrentState  = SERVICE_STOPPED;   
  55.         ServiceStatus.dwCheckPoint    = 0;   
  56.         ServiceStatus.dwWaitHint      = 0;  
  57.         uaquit= 1;  
  58.         //add you quit code here  
  59.         if(log != NULL)  
  60.             fclose(log);  
  61.         break;   
  62.         default:  
  63.             return;   
  64.     };  
  65.     if (!SetServiceStatus(hServiceStatusHandle,  &ServiceStatus))   
  66.     {   
  67.         DWORD nError = GetLastError();  
  68.     }   
  69. }  
  70.   
  71.     
  72. void WINAPI service_main(int argc, char** argv)   
  73. {         
  74.     ServiceStatus.dwServiceType        = SERVICE_WIN32;   
  75.     ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;   
  76.     ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;   
  77.     ServiceStatus.dwWin32ExitCode      = 0;   
  78.     ServiceStatus.dwServiceSpecificExitCode = 0;   
  79.     ServiceStatus.dwCheckPoint         = 0;   
  80.     ServiceStatus.dwWaitHint           = 0;    
  81.     hServiceStatusHandle = RegisterServiceCtrlHandler(_T(SERVICE_NAME), ServiceHandler);   
  82.     if (hServiceStatusHandle==0)   
  83.     {  
  84.         DWORD nError = GetLastError();  
  85.     }    
  86.     //add your init code here  
  87.     log = fopen("d:\\test.txt","w");  
  88.     //add your service thread here  
  89.     HANDLE task_handle = CreateThread(NULL,NULL,srv_core_thread,NULL,NULL,NULL);  
  90.     if(task_handle == NULL)  
  91.     {  
  92.         fprintf(log,"create srv_core_thread failed\n");  
  93.     }  
  94.       
  95.     // Initialization complete - report running status   
  96.     ServiceStatus.dwCurrentState       = SERVICE_RUNNING;   
  97.     ServiceStatus.dwCheckPoint         = 0;   
  98.     ServiceStatus.dwWaitHint           = 9000;    
  99.     if(!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))   
  100.     {   
  101.         DWORD nError = GetLastError();  
  102.     }   
  103.    
  104. }   
  105. //do not change main function  
  106. int main (int argc, const char *argv[])  
  107. {  
  108.     SERVICE_TABLE_ENTRY ServiceTable[2];  
  109.       
  110.     ServiceTable[0].lpServiceName = _T(SERVICE_NAME);  
  111.     ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;  
  112.       
  113.     ServiceTable[1].lpServiceName = NULL;  
  114.     ServiceTable[1].lpServiceProc = NULL;  
  115.     // 启动服务的控制分派机线程  
  116.     StartServiceCtrlDispatcher(ServiceTable);   
  117.     return 0;  
  118. }  

2、加服务事件
[cpp] view plaincopy
  1. // ServiceTest.cpp : Defines the entry point for the application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "stdio.h"  
  6. #include "tchar.h"  
  7. #include <windows.h>  
  8. #include<iostream>  
  9. using namespace std;  
  10.   
  11.   
  12. //定义全局函数变量  
  13. void Init();  
  14. BOOL IsInstalled();  
  15. BOOL Install();  
  16. BOOL Uninstall();  
  17. void LogEvent(LPCTSTR pszFormat, ...);  
  18. void WINAPI ServiceMain();  
  19. void WINAPI ServiceStrl(DWORD dwOpcode);  
  20.   
  21. TCHAR szServiceName[] = _T("ServiceTest");  
  22. BOOL bInstall;  
  23. SERVICE_STATUS_HANDLE hServiceStatus;  
  24. SERVICE_STATUS status;  
  25. DWORD dwThreadID;  
  26.   
  27. int APIENTRY WinMain(HINSTANCE hInstance,  
  28.                      HINSTANCE hPrevInstance,  
  29.                      LPSTR     lpCmdLine,  
  30.                      int       nCmdShow)  
  31. {  
  32.     Init();  
  33.       
  34.     dwThreadID = ::GetCurrentThreadId();  
  35.   
  36.     SERVICE_TABLE_ENTRY st[] =  
  37.     {  
  38.         { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },  
  39.         { NULL, NULL }  
  40.     };  
  41.   
  42.     if (stricmp(lpCmdLine, "/install") == 0)  
  43.     {  
  44.         Install();  
  45.     }  
  46.     else if (stricmp(lpCmdLine, "/uninstall") == 0)  
  47.     {  
  48.         Uninstall();  
  49.     }  
  50.     else  
  51.     {  
  52.         if (!::StartServiceCtrlDispatcher(st))  
  53.         {  
  54.             LogEvent(_T("Register Service Main Function Error!"));  
  55.         }  
  56.     }  
  57.   
  58.     return 0;  
  59. }  
  60. //*********************************************************  
  61. //Functiopn:            Init  
  62. //Description:            初始化  
  63. //Calls:                main  
  64. //Called By:                  
  65. //Table Accessed:                  
  66. //Table Updated:                  
  67. //Input:                  
  68. //Output:                  
  69. //Return:                  
  70. //Others:                  
  71. //History:                  
  72. //            <author>niying <time>2006-8-10        <version>        <desc>  
  73. //*********************************************************  
  74. void Init()  
  75. {  
  76.     hServiceStatus = NULL;  
  77.     status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;  
  78.     status.dwCurrentState = SERVICE_STOPPED;  
  79.     status.dwControlsAccepted = SERVICE_ACCEPT_STOP;  
  80.     status.dwWin32ExitCode = 0;  
  81.     status.dwServiceSpecificExitCode = 0;  
  82.     status.dwCheckPoint = 0;  
  83.     status.dwWaitHint = 0;  
  84. }  
  85.   
  86. //*********************************************************  
  87. //Functiopn:            ServiceMain  
  88. //Description:            服务主函数,这在里进行控制对服务控制的注册  
  89. //Calls:  
  90. //Called By:  
  91. //Table Accessed:  
  92. //Table Updated:  
  93. //Input:  
  94. //Output:  
  95. //Return:  
  96. //Others:  
  97. //History:  
  98. //            <author>niying <time>2006-8-10        <version>        <desc>  
  99. //*********************************************************  
  100. void WINAPI ServiceMain()  
  101. {  
  102.     // Register the control request handler  
  103.     status.dwCurrentState = SERVICE_START_PENDING;  
  104.     status.dwControlsAccepted = SERVICE_ACCEPT_STOP;  
  105.   
  106.     //注册服务控制  
  107.     hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceStrl);  
  108.     if (hServiceStatus == NULL)  
  109.     {  
  110.         LogEvent(_T("Handler not installed"));  
  111.         return;  
  112.     }  
  113.     SetServiceStatus(hServiceStatus, &status);  
  114.   
  115.     status.dwWin32ExitCode = S_OK;  
  116.     status.dwCheckPoint = 0;  
  117.     status.dwWaitHint = 0;  
  118.     status.dwCurrentState = SERVICE_RUNNING;  
  119.     SetServiceStatus(hServiceStatus, &status);  
  120.   
  121.     //模拟服务的运行,10后自动退出。应用时将主要任务放于此即可  
  122.     int i = 0;  
  123.     while (i < 10)  
  124.     {   
  125.   
  126.         //新建文件  
  127.         FILE * fp0=fopen("c:/tt.txt","a");  
  128.         fclose(fp0);  
  129.         Sleep(10000);  
  130.         i++;  
  131.     }  
  132.     //  
  133.   
  134.     status.dwCurrentState = SERVICE_STOPPED;  
  135.     SetServiceStatus(hServiceStatus, &status);  
  136.     LogEvent(_T("Service stopped"));  
  137. }  
  138.   
  139. //*********************************************************  
  140. //Functiopn:            ServiceStrl  
  141. //Description:            服务控制主函数,这里实现对服务的控制,  
  142. //                        当在服务管理器上停止或其它操作时,将会运行此处代码  
  143. //Calls:  
  144. //Called By:  
  145. //Table Accessed:  
  146. //Table Updated:  
  147. //Input:                dwOpcode:控制服务的状态  
  148. //Output:  
  149. //Return:  
  150. //Others:  
  151. //History:  
  152. //            <author>niying <time>2006-8-10        <version>        <desc>  
  153. //*********************************************************  
  154. void WINAPI ServiceStrl(DWORD dwOpcode)  
  155. {  
  156.     switch (dwOpcode)  
  157.     {  
  158.     case SERVICE_CONTROL_STOP:  
  159.         status.dwCurrentState = SERVICE_STOP_PENDING;  
  160.         SetServiceStatus(hServiceStatus, &status);  
  161.         PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);  
  162.         break;  
  163.     case SERVICE_CONTROL_PAUSE:  
  164.         break;  
  165.     case SERVICE_CONTROL_CONTINUE:  
  166.         break;  
  167.     case SERVICE_CONTROL_INTERROGATE:  
  168.         break;  
  169.     case SERVICE_CONTROL_SHUTDOWN:  
  170.         break;  
  171.     default:  
  172.         LogEvent(_T("Bad service request"));  
  173.     }  
  174. }  
  175. //*********************************************************  
  176. //Functiopn:            IsInstalled  
  177. //Description:            判断服务是否已经被安装  
  178. //Calls:  
  179. //Called By:  
  180. //Table Accessed:  
  181. //Table Updated:  
  182. //Input:  
  183. //Output:  
  184. //Return:  
  185. //Others:  
  186. //History:  
  187. //            <author>niying <time>2006-8-10        <version>        <desc>  
  188. //*********************************************************  
  189. BOOL IsInstalled()  
  190. {  
  191.     BOOL bResult = FALSE;  
  192.   
  193.     //打开服务控制管理器  
  194.     SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  
  195.   
  196.     if (hSCM != NULL)  
  197.     {  
  198.         //打开服务  
  199.         SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_QUERY_CONFIG);  
  200.         if (hService != NULL)  
  201.         {  
  202.             bResult = TRUE;  
  203.             ::CloseServiceHandle(hService);  
  204.         }  
  205.         ::CloseServiceHandle(hSCM);  
  206.     }  
  207.     return bResult;  
  208. }  
  209.   
  210. //*********************************************************  
  211. //Functiopn:            Install  
  212. //Description:            安装服务函数  
  213. //Calls:  
  214. //Called By:  
  215. //Table Accessed:  
  216. //Table Updated:  
  217. //Input:  
  218. //Output:  
  219. //Return:  
  220. //Others:  
  221. //History:  
  222. //            <author>niying <time>2006-8-10        <version>        <desc>  
  223. //*********************************************************  
  224. BOOL Install()  
  225. {  
  226.     if (IsInstalled())  
  227.         return TRUE;  
  228.   
  229.     //打开服务控制管理器  
  230.     SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  
  231.     if (hSCM == NULL)  
  232.     {  
  233.         MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);  
  234.         return FALSE;  
  235.     }  
  236.   
  237.     // Get the executable file path  
  238.     TCHAR szFilePath[MAX_PATH];  
  239.     ::GetModuleFileName(NULL, szFilePath, MAX_PATH);  
  240.   
  241.     //创建服务  
  242.     SC_HANDLE hService = ::CreateService(  
  243.         hSCM, szServiceName, szServiceName,  
  244.         SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,  
  245.         SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,  
  246.         szFilePath, NULL, NULL, _T(""), NULL, NULL);  
  247.   
  248.     if (hService == NULL)  
  249.     {  
  250.         ::CloseServiceHandle(hSCM);  
  251.         MessageBox(NULL, _T("Couldn't create service"), szServiceName, MB_OK);  
  252.         return FALSE;  
  253.     }  
  254.   
  255.     ::CloseServiceHandle(hService);  
  256.     ::CloseServiceHandle(hSCM);  
  257.     return TRUE;  
  258. }  
  259.   
  260. //*********************************************************  
  261. //Functiopn:            Uninstall  
  262. //Description:            删除服务函数  
  263. //Calls:  
  264. //Called By:  
  265. //Table Accessed:  
  266. //Table Updated:  
  267. //Input:  
  268. //Output:  
  269. //Return:  
  270. //Others:  
  271. //History:  
  272. //            <author>niying <time>2006-8-10        <version>        <desc>  
  273. //*********************************************************  
  274. BOOL Uninstall()  
  275. {  
  276.     if (!IsInstalled())  
  277.         return TRUE;  
  278.   
  279.     SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  
  280.   
  281.     if (hSCM == NULL)  
  282.     {  
  283.         MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);  
  284.         return FALSE;  
  285.     }  
  286.   
  287.     SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);  
  288.   
  289.     if (hService == NULL)  
  290.     {  
  291.         ::CloseServiceHandle(hSCM);  
  292.         MessageBox(NULL, _T("Couldn't open service"), szServiceName, MB_OK);  
  293.         return FALSE;  
  294.     }  
  295.     SERVICE_STATUS status;  
  296.     ::ControlService(hService, SERVICE_CONTROL_STOP, &status);  
  297.   
  298.     //删除服务  
  299.     BOOL bDelete = ::DeleteService(hService);  
  300.     ::CloseServiceHandle(hService);  
  301.     ::CloseServiceHandle(hSCM);  
  302.   
  303.     if (bDelete)  
  304.         return TRUE;  
  305.   
  306.     LogEvent(_T("Service could not be deleted"));  
  307.     return FALSE;  
  308. }  
  309.   
  310. //*********************************************************  
  311. //Functiopn:            LogEvent  
  312. //Description:            记录服务事件  
  313. //Calls:  
  314. //Called By:  
  315. //Table Accessed:  
  316. //Table Updated:  
  317. //Input:  
  318. //Output:  
  319. //Return:  
  320. //Others:  
  321. //History:  
  322. //            <author>niying <time>2006-8-10        <version>        <desc>  
  323. //*********************************************************  
  324. void LogEvent(LPCTSTR pFormat, ...)  
  325. {  
  326.     TCHAR    chMsg[256];  
  327.     HANDLE  hEventSource;  
  328.     LPTSTR  lpszStrings[1];  
  329.     va_list pArg;  
  330.   
  331.     va_start(pArg, pFormat);  
  332.     _vstprintf(chMsg, pFormat, pArg);  
  333.     va_end(pArg);  
  334.   
  335.     lpszStrings[0] = chMsg;  
  336.       
  337.     hEventSource = RegisterEventSource(NULL, szServiceName);  
  338.     if (hEventSource != NULL)  
  339.     {  
  340.         ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);  
  341.         DeregisterEventSource(hEventSource);  
  342.     }  
  343. }  
0 0
原创粉丝点击