本文将首先解释如何 创建 一个定期查询可用物理内存并将结果写入某个文本文件的服务。然后指导你完成生成,安装和实现服务的整个过程。

第一步:主函数和全局定义

首先,包含所需的头文件。例子要调用 Win32 函数(windows.h )和磁盘文件写入(stdio.h ):

接着,定义两个常量:

#define SLEEP_TIME 5000
#define LOGFILE "C:\\MyServices\\memstatus.txt"
SLEEP_TIME 指定两次连续查询可用内存之间的毫秒间隔。在第二步中编写服务工作循环的时候要使用该常量。 
LOGFILE 定义日志文件的路径,你将会用 WriteToLog 函数将内存查询的结果输出到该文件,WriteToLog 函数定义如下:

int WriteToLog(char* str)
{
     FILE* log;
     log = fopen(LOGFILE, "a+");//如果VS非TMD提示不安全,则在“属性->配置属性->c/c++->命令行”中添加“/D_CRT_SECURE_NO_WARNINGS ”
     if (log == NULL)
     return -1;
     fprintf(log, "%s\n", str);
     fclose(log);
     return 0;
}
声明几个全局变量,以便在程序的多个函数之间共享它们值。此外,做一个函数的前向定义:

SERVICE_STATUS ServiceStatus; 
SERVICE_STATUS_HANDLE hStatus;

void ServiceMain(int argc, char** argv); 
void ControlHandler(DWORD request); 
int InitService();
  现在,准备工作已经就绪,你可以开始编码了。服务程序控制台程序的一个子集。因此,开始你可以定义一个 main 函数,它是程序的入口点。对于服务程序来说,main 的代码令人惊讶地简短,因为它只创建分派表并启动控制分派机。

void main() 

     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); 
}
  一个程序可能包含若干个服务。每一个服务都必须列于专门的分派表中(为此该程序定义了一个 ServiceTable 结构数组)。这个表中的每一项都要在 SERVICE_TABLE_ENTRY 结构之中。它有两个域:

lpServiceName: 指向表示服务名称字符串的指针;当定义了多个服务时,那么这个域必须指定; 
lpServiceProc: 指向服务主函数的指针(服务入口点); 
  分派表的最后一项必须是服务名和服务主函数域的 NULL 指针,文本例子程序中只宿主一个服务,所以服务名的定义是可选的。 
  服务控制管理器(SCM :Services Control Manager )是一个管理系统所有服务的进程。当 SCM 启动某个服务时,它等待某个进程的主线程来调用 StartServiceCtrlDispatcher 函数。将分派表传递给 StartServiceCtrlDispatcher 。这将把调用进程的主线程转换为控制分派器。该分派器启动一个新线程,该线程运行分派表中每个服务的 ServiceMain 函数(本文例子中只有一个服务)分派器还监视程序中所有服务的执行情况。然后分派器将控制请求从 SCM 传给服务。

注意:如果 StartServiceCtrlDispatcher 函数30 秒没有被调用,便会报错,为了避免这种情况,我们必须在 ServiceMain 函数中(参见本文例子)或在非主函数的单独线程中初始化服务分派表。本文所描述的服务不需要防范这样的情况。

  分派表中所有的服务执行完之后(例如,用户通过“ 服务” 控制面板程序停止它们),或者发生错误时。StartServiceCtrlDispatcher 调用返回。然后主进程终止。

第二步:ServiceMain 函数

  Listing 1 展示了 ServiceMain 的代码。该函数是服务的入口点。它运行在一个单独的线程当中,这个线程是由控制分派器创建的。ServiceMain 应该尽可能早早为服务注册控制处理器。这要通过调用 RegisterServiceCtrlHadler 函数来实现。你要将两个参数传递给此函数:服务名和指向 ControlHandlerfunction 的指针。 
  它指示控制分派器调用 ControlHandler 函数处理 SCM 控制请求。注册完控制处理器之后,获得状态句柄(hStatus )。通过调用 SetServiceStatus 函数,用 hStatus 向 SCM 报告服务的状态。 
Listing 1 展示了如何指定服务特征和其当前状态来初始化 ServiceStatus 结构,ServiceStatus 结构的每个域都有其用途:

dwServiceType :指示服务类型,创建 Win32 服务。赋值 SERVICE_WIN32 ; 
dwCurrentState :指定服务的当前状态。因为服务的初始化在这里没有完成,所以这里的状态为 SERVICE_START_PENDING ; 
dwControlsAccepted :这个域通知 SCM 服务接受哪个域。本文例子是允许 STOP 和 SHUTDOWN 请求。处理控制请求将在第三步讨论; 
dwWin32ExitCode 和 dwServiceSpecificExitCode :这两个域在你终止服务并报告退出细节时很有用。初始化服务时并不退出,因此,它们的值为 0 ; 
dwCheckPoint 和 dwWaitHint :这两个域表示初始化某个服务进程时要30 秒以上。本文例子服务的初始化过程很短,所以这两个域的值都为 0 。 
  调用 SetServiceStatus 函数向 SCM 报告服务的状态时。要提供 hStatus 句柄和 ServiceStatus 结构。注意 ServiceStatu 一个全局变量,所以你可以跨多个函数使用它。ServiceMain 函数中,你给结构的几个域赋值,它们在服务运行的整个过程中都保持不变,比如:dwServiceType 。 
  在报告了服务状态之后,你可以调用 InitService 函数来完成初始化。这个函数只是添加一个说明性字符串到日志文件。如下面代码所示:

// 服务初始化 
int InitService() 

     int result;
     result = WriteToLog("Monitoring started.");
     return(result); 
}
  在 ServiceMain 中,检查 InitService 函数的返回值。如果初始化有错(因为有可能写日志文件失败),则将服务状态置为终止并退出 ServiceMain :

error = InitService(); 
if (error) 
{
     // 初始化失败,终止服务 
     ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
     ServiceStatus.dwWin32ExitCode = -1; 
     SetServiceStatus(hStatus, &ServiceStatus); 
     // 退出 ServiceMain
     return; 
}
如果初始化成功,则向 SCM 报告状态:

// 向 SCM 报告运行状态 
ServiceStatus.dwCurrentState = SERVICE_RUNNING; 
SetServiceStatus (hStatus, &ServiceStatus);
接着,启动工作循环。每五秒钟查询一个可用物理内存并将结果写入日志文件。

如 Listing 1 所示,循环一直到服务的状态为 SERVICE_RUNNING 或日志文件写入出错为止。状态可能在 ControlHandler 函数响应 SCM 控制请求时修改。

第三步:处理控制请求

  在第二步中,你用 ServiceMain 函数注册了控制处理器函数。控制处理器与处理各种 Windows 消息的窗口回调函数非常类似。它检查 SCM 发送了什么请求并采取相应行动。 
  每次你调用 SetServiceStatus 函数的时候,必须指定服务接收 STOP 和 SHUTDOWN 请求。Listing 2 示范了如何在 ControlHandler 函数中处理它们。 
  STOP 请求是 SCM 终止服务的时候发送的。例如,如果用户在“ 服务” 控制面板中手动终止服务。SHUTDOWN 请求是关闭机器时,由 SCM 发送给所有运行中服务的请求。两种情况的处理方式相同:

写日志文件,监视停止; 
向 SCM 报告 SERVICE_STOPPED 状态; 
  由于 ServiceStatus 结构对于整个程序而言为全局量,ServiceStatus 中的工作循环在当前状态改变或服务终止后停止。其它的控制请求如:PAUSE 和 CONTINUE 在本文的例子没有处理。 
  控制处理器函数必须报告服务状态,即便 SCM 每次发送控制请求的时候状态保持相同。因此,不管响应什么请求,都要调用 SetServiceStatus 。

第四步:安装和配置服务

  程序编好了,将之编译成 exe 文件。本文例子创建的文件叫 MemoryStatus.exe ,将它拷贝到 C:\MyServices 文件夹。为了在机器上安装这个服务,需要用 SC.EXE 可执行文件,它是 Win32 Platform SDK 中附带的一个工具。(译者注:Visaul Studio .NET 2003 IDE 环境中也有这个工具,具体存放位置在:C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\Bin\winnt )。使用这个实用工具可以安装和移除服务。其它控制操作将通过服务控制面板来完成。以下是用命令行安装 MemoryStatus 服务的方法:

sc create MemoryStatus binpath= c:\MyServices\MemoryStatus.exe
  发出此创建命令。指定服务名和二进制文件的路径(注意 binpath= 和路径之间的那个空格)。安装成功后,便可以用服务控制面板来控制这个服务。用控制面板的工具栏启动和终止这个服务。

 MemoryStatus 的启动类型是手动,也就是说根据需要来启动这个服务。右键单击该服务,然后选择上下文菜单中的“ 属性” 菜单项,此时显示该服务的属性窗口。在这里可以修改 启动类型以及其它设置。你还可以从“ 常规” 标签中启动/ 停止服务。以下是从系统中移除服务的方法:

sc delete MemoryStatus
指定 “delete” 选项和服务名。此服务将被标记为删除,下次西通重启后,该服务将被完全移除。 
第五步:测试服务

  从服务控制面板启动 MemoryStatus 服务。如果初始化不出错,表示启动成功。过一会儿将服务停止。检查一下 C:\MyServices 文件夹中 memstatus.txt 文件的服务输出。
  为了测试 MemoryStatus 服务在出错情况下的行为,可以将 memstatus.txt 文件设置成只读。这样一来,服务应该无法启动。 
  去掉只读属性,启动服务,在将文件设成只读。服务将停止执行,因为此时日志文件写入失败。如果你更新服务控制面板的内容,会发现服务状态是已经停止。

  1. #include "stdafx.h"
  2. #include <windows.h>
  3. #pragma comment(lib, "Advapi32")
  4. #define SLEEP_TIME 5000
  5. #define LOGFILE "d:\\memstatus.txt"
  6.  
  7. SERVICE_STATUS ServiceStatus;
  8. SERVICE_STATUS_HANDLE hStatus;
  9. void ServiceMain(int argc, char** argv);
  10. void ControlHandler(DWORD request);
  11. int InitService();
  12. int WriteToLog(char* str);
  13.  
  14. int main(int argc, char* argv[])
  15. {
  16. SERVICE_TABLE_ENTRY ServiceTable[];
  17. ServiceTable[].lpServiceName = "MemoryStatus";
  18. ServiceTable[].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
  19.  
  20. ServiceTable[].lpServiceName = NULL;
  21. ServiceTable[].lpServiceProc = NULL;
  22. // 启动服务的控制分派机线程
  23. StartServiceCtrlDispatcher(ServiceTable);
  24.  
  25.   //注册并启动服务,需要以管理员身份运行VS
       system("sc create abcde binPath= \"E:\\visual studio 2012\\Projects\\sc_study\\Debug\\sc_study.exe \"");//服务名任意
        system("sc start abcde");
     // system("sc stop abcde");
     // system("sc delete abcde");
        system("pause");
  26. }
  27.  
  28. void ServiceMain(int argc, char** argv)
  29. {
  30. int error;
  31.  
  32. ServiceStatus.dwServiceType =
  33. SERVICE_WIN32;
  34. ServiceStatus.dwCurrentState =
  35. SERVICE_START_PENDING;
  36. ServiceStatus.dwControlsAccepted =
  37. SERVICE_ACCEPT_STOP |
  38. SERVICE_ACCEPT_SHUTDOWN;
  39. ServiceStatus.dwWin32ExitCode = ;
  40. ServiceStatus.dwServiceSpecificExitCode = ;
  41. ServiceStatus.dwCheckPoint = ;
  42. ServiceStatus.dwWaitHint = ;
  43.  
  44. hStatus = RegisterServiceCtrlHandler(
  45. "MemoryStatus",
  46. (LPHANDLER_FUNCTION)ControlHandler);
  47. if (hStatus == (SERVICE_STATUS_HANDLE))
  48. {
  49. // Registering Control Handler failed
  50. return;
  51. }
  52. // Initialize Service
  53. error = InitService();
  54. if (!error)
  55. {
  56. // Initialization failed
  57. ServiceStatus.dwCurrentState =
  58. SERVICE_STOPPED;
  59. ServiceStatus.dwWin32ExitCode = -;
  60. SetServiceStatus(hStatus, &ServiceStatus);
  61. return;
  62. }
  63. // We report the running status to SCM.
  64. ServiceStatus.dwCurrentState =
  65. SERVICE_RUNNING;
  66. SetServiceStatus (hStatus, &ServiceStatus);
  67.  
  68. MEMORYSTATUS memory;
  69. // The worker loop of a service
  70. while (ServiceStatus.dwCurrentState ==
  71. SERVICE_RUNNING)
  72. {
  73. char buffer[];
  74. GlobalMemoryStatus(&memory);
  75. sprintf_s(buffer, "%d", memory.dwAvailPhys);
  76. int result = WriteToLog(buffer);
  77. if (result)
  78. {
  79. ServiceStatus.dwCurrentState =
  80. SERVICE_STOPPED;
  81. ServiceStatus.dwWin32ExitCode = -;
  82. SetServiceStatus(hStatus,
  83. &ServiceStatus);
  84. return;
  85. }
  86. Sleep(SLEEP_TIME);
  87. }
  88. return;
  89. }
  90.  
  91. void ControlHandler(DWORD request)
  92. {
  93. switch(request)
  94. {
  95. case SERVICE_CONTROL_STOP:
  96. WriteToLog("Monitoring stopped.");
  97. ServiceStatus.dwWin32ExitCode = ;
  98. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  99. SetServiceStatus (hStatus, &ServiceStatus);
  100. return;
  101.  
  102. case SERVICE_CONTROL_SHUTDOWN:
  103. WriteToLog("Monitoring stopped.");
  104. ServiceStatus.dwWin32ExitCode = ;
  105. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  106. SetServiceStatus (hStatus, &ServiceStatus);
  107. return;
  108.  
  109. default:
  110. break;
  111. }
  112.  
  113. // Report current status
  114. SetServiceStatus (hStatus, &ServiceStatus);
  115.  
  116. return;
  117. }
  118.  
  119. int WriteToLog(char* str)
  120. {
  121. FILE* log;
  122. log = fopen(LOGFILE, "a+");
  123. if (log == NULL)
  124. return -;
  125. fprintf(log, "%s ", str);
  126. fclose(log);
  127. return ;
  128. }
  129. int InitService(){
  130. WriteToLog("Monitoring started.");
  131. return true;
  132. }

 以管理员身份运行程序的步骤:

1、在VS“配置属性”->"连接器"->"清单文件"->"UAC执行级别"选择requireAdministrator

2、重新编译工程,此时生成的exe图标上就出现个小盾牌aaarticlea/png;base64,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" alt="" />,运行时就提示以管理员身份运行了

windows服务编写和“以管理员运行”程序的方法的更多相关文章

  1. [转载]Windows服务编写原理及探讨(1)

    有那么一类应用程序,是能够为各种用户(包括本地用户和远程用户)所用的,拥有用户授权级进行管理的能力,并且不论用户是否物理的与正在运行该应用程序的计算机相连都能正常执行,这就是所谓的服务了. (一)服务 ...

  2. 如何优雅的利用Windows服务来部署ASP.NET Core程序

    上一篇文章中我给大家讲述了五种部署ASP.NET Core网站的方法,其中有一种方式是通过Windows服务来进行部署,这样既可以做到开启自启动,又不会因为iis的反向代理而损失部分性能.但是美中不足 ...

  3. 如何将exe注册为windows服务,直接从后台运行

    方法一:使用windows自带的命令sc 使用sc create 方法创建. 如:注册服务 sc create ResharperServices binpath= D:\ResharperServi ...

  4. [转载]Windows服务编写原理及探讨(4)

    (四)一些问题的讨论 前面几章的内容都是服务的一些通用的编写原理,但里面隐含着一些问题,编写简单的服务时看不出来,但遇到复杂的应用就会出现一些问题,所以本章就是用来分析.解决这些问题的,适用于高级应用 ...

  5. 给windows服务打包,并生成安装程序

    一. 添加新建项目-->安装部署-->安装项目 二.安装程序上-->右键视图-->文件系统-->应用程序文件夹-->右键-->添加项目输出 选择做好的wind ...

  6. C# windows 服务编写及安装

      最近项目中用到window服务程序,以前没接触过,比较陌生,花了两天的时间学习了下,写了个简单的服务,但在制作安装程序的时候,参照网上很多资料,却都制作不成功,可能是开发环境或项目配置的不同,这里 ...

  7. [转载]Windows服务编写原理及探讨(3)

    (三)对服务的深入讨论之下 现在我们还剩下一个函数可以在细节上讨论,那就是服务的CtrlHandler函数. 当调用RegisterServiceCtrlHandler函数时,SCM得到并保存这个回调 ...

  8. [转载]Windows服务编写原理及探讨(2)

    (二)对服务的深入讨论之上 上一章其实只是概括性的介绍,下面开始才是真正的细节所在.在进入点函数里面要完成ServiceMain的初始化,准确点说是初始化一个 SERVICE_TABLE_ENTRY结 ...

  9. Win8如何默认以管理员运行程序

    在Win7的时候,关闭UAC,使用自己的用户名,所有程序都是默认以管理员身份运行的. 但是在Win8,关闭UAC,程序不是默认以管理员身份运行的. 在论坛看到的解决方法是:1.用Administrat ...

随机推荐

  1. nginx流量全copy记录

    参考:http://tyrion.iteye.com/blog/2311987 准备两台服务器: 0.0.0.1 0.0.0.2 在 0.0.0.1上 . 下载 wget https://github ...

  2. 关于synchronized关键字

    1.synchronized关键字的作用域有二种: 1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有 ...

  3. qemu-kvm 代码分析

    qemu-kvm 代码分析 虚拟机组成 实际上面所说计算机组成比较笼统,实际处理器,存储器,输入与设备种类繁多,     -   i440FX host PCI bridge and PIIX3 PC ...

  4. js抽象工厂模式

    抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么.这样客户就可以从具体 ...

  5. myeclipse发布项目

    最好不要点击restart 虽然点击run,也会发布,但是最好先点击发布. 点击restart,可能会出现tomcat关不掉又启动不了.

  6. 添加语句<tx:annotation-driven transaction-manager="txManager"/>报错

    在添加<tx:annotation-driven transaction-manager="txManager"/>程序之前,applicationContext.xm ...

  7. SQL SERVER 集合

    死锁和堵塞一直是性能测试执行中关注的重点. 下面是我整理的监控sql server数据库,在性能测试过程中是否出现死锁.堵塞的SQL语句,还算比较准备,留下来备用. --每秒死锁数量 SELECT * ...

  8. Sublime Text3取消自动补全结束标签

    点击首选项——设置-用户——在配置中增加一句:"auto_close_tags": false, 参考来源:豆瓣小组:求解Sublime Text 3怎么取消自动补全结束标签

  9. mybatis报Error updating database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String

    mybatis 3.3.0中对于时间参数进行比较时的一个bug. 如果拿传入的时间类型参数与空字符串''进行对比判断则会引发异常. 所以在上面的代码中去该该判断, 只保留非空判断就正常了 <if ...

  10. 关于js冒泡、捕获、以及阻止冒泡

    有如下html <ul> <li> <p> <a href="javascript:;">click me</a> &l ...