Windows服务学习一
来源:互联网 发布:国家网络应急中心待遇 编辑:程序博客网 时间:2024/05/16 03:51
关于Windows服务编程的学习,在网上搜索还是很多的。
恩,个人最近总是不在状态啊,看代码看着就睡着了,只好自己写篇博客,来加深下印象了,所有资料都是从网上收集的,个人整合了一下。
一、什么是Windows Service
Windows Service 是一种可随 Windows 操作系统启动而启动的,在后台运行的,通常不和用户产生交互的程序。它无法通过双击来运行,类似于 Unix 守护进程(daemon processes),当用户注销时它也不会停止。
Windows 服务由三部分组成:1.一个服务可执行文件;2.一个服务控制程序(SCP);3.服务控制管理器(SCM),负责在 HKLM/SYSTEM/CurrentControlSet/Services 下创建服务键值。用户可通过 SCP 控制服务的启动、停止、暂停等,SCP 会通过 SCM 调用服务程序。
Window 标准的exe可执行程序通常有一个用户界面,Console或GUI,通常由用户来启动或停止
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ojlovecd/archive/2008/05/07/2412564.aspx
二、如何编写Windows Service
我们编写的服务,其实就是要编写在上面所说的Windows服务三部分组成之一的第一点 服务可执行文件,而服务控制程序和服务控制管理器是Windows本身就有的,我们要实现的就是将我们编写的服务可执行文件编写安装到Windows内并向服务控制管理器注册服务,也方便服务控制程序能够对我们的服务进行操作。所以其实是很简单的。
下面分步讲解完成过程:
1、要创建一个服务我们首先就要告诉服务控制管理器:“我们要创建一个服务”,它会告诉你是不是可以创建一个服务。如何告诉呢,很简单,如下:
//打开服务控制管理器
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
参数说明:
其中第一个参数是要在那个电脑上创建服务啊,如果是本机的话,直接使用NULL就可以了,否则该参数是一个'/0'结尾的字符串,并且前缀必须是“//”。
第二个参数是要打开服务控制管理器的名称,一般设为SERVICES_ACTIVE_DATABASE或是NULL均可。
第三个是设置访问权限了,SC_MANAGER_ALL_ACCESS是设置可以访问所有,具体的此处不在罗列。
当然该函数的返回值是我们调用函数的结果是一个SC_HANDLE类型,一看就知道是服务控制器的句柄了。
我们要调用了,当让是对我们有好处的了,不然我闲着没事干了,我们就是要用它的返回值作为下一个函数的句柄,如下:
//创建服务
SC_HANDLE hService = ::CreateService(
hSCM, //服务控制器句柄了
szServiceName, //创建的服务名称 最长256个字符 无大小写之分 不能包含/和/字符
szServiceName, //显示的名称 最长256个字符 无大小写之分
SERVICE_ALL_ACCESS, //访问权限
SERVICE_WIN32_OWN_PROCESS,//服务类型
SERVICE_DEMAND_START, //指出服务何时开始
SERVICE_ERROR_NORMAL, //指出启动出错后如何处理
szFilePath, //生成可执行文件路径 如果路径包含空格 要用引号
NULL,//如果服务属于组,则制定顺序装入服务组名
NULL, //用来接收标志值,在组中使用的
_T(""),//制定启动该服务前要启动的服务或服务组
NULL,//以NULL结尾的字符串,指定服务帐号,如果为NULL则是LocalSystem帐号
NULL); //以NULL结尾的字符串,制定对应的口令,LocalSystem时为NULL
//创建服务后关掉句柄
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
上面的过程是创建了一个服务,其实就是常说的安装了一个服务了。有创建自然就有删除,如果说是安装那也就得有卸载吧,下面就是卸载了。
2、服务的删除(卸载):
{
SERVICE_TABLE_ENTRY ServiceTable[2];//服务表入口,该结果的最后必须以NULL结尾
ServiceTable[0].lpServiceName = "MemoryStatus";//服务名称
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
//一个程序可以包含如干个服务,每个服务都必须列于专门的分派表中,此处只有一个服务。
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// 启动服务的控制分派机线程,该函数在30秒钟没有调用会报错,为此我们在此不能够做更多的工作
StartServiceCtrlDispatcher(ServiceTable);
}
上面提到了一个函数ServiceMain,该函数就是服务的入口点。它运行在一个单独的线程当中,这个线程是由控制分派器创建的(当然我们没有看到CreateThread类似的函数)。ServiceMain应该早早地为服务注册服务控制处理器,该注册是通过函数RegisterServiceCtrlHandler来实现,我们只需要传递给该函数两个参数(服务名和控制处理函数的地址)即可。注册完成后返回服务状态句柄,我们就可以通过该函数实现对服务状态的操作了。如下:
SERVICE_STATUS ServiceStatus;//服务状态
SERVICE_STATUS_HANDLE hStatus; //服务状态句柄
ServiceStatus.dwServiceType =
SERVICE_WIN32; //设置为WIN32服务
ServiceStatus.dwCurrentState =
SERVICE_START_PENDING; //开始时并不允许
ServiceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP | //要使用SERVICE_ACCEPT_STOP 否则我们不能控制服务
SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0; //在终止服务时使用,此处设为0
ServiceStatus.dwServiceSpecificExitCode = 0; //在终止服务时使用
ServiceStatus.dwCheckPoint = 0; //这两个域表示初始化某个服务进程时要30秒以上。本文例
ServiceStatus.dwWaitHint = 0; //子服务的初始化过程很短,所以这两个域的值都为 0。
hStatus = RegisterServiceCtrlHandler(
"MemoryStatus", //为服务名为MemoryStatus的服务注册控制器函数为ControlHander
(LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0) //判断是否注册成功
{
// Registering Control Handler failed
return;
}
//上面没有错后就设置服务状态为运行状态并调用SetServiceStatus向SCM报告
ServiceStatus.dwCurrentState =
SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);
接着在ServiceMain函数中完成上面的工作后,我们就可以开始执行我们自己的工作了。
具体的请参看如下两篇文章,很谢谢他们的分享,本文相当的于是看这两篇文章后的笔记吧。
http://www.vckbase.com/document/viewdoc/?id=1474
http://blog.csdn.net/xiaohuaidan717/archive/2006/12/08/1434508.aspx
- Windows服务学习一
- Windows服务学习一
- Windows 服务(一)
- windows 服务学习笔记
- Windows服务学习二
- windows服务开发学习
- C# windows 服务学习探索
- windows 服务 SCM学习笔记
- windows学习20150128 之 windows服务
- windows编程学习<一>
- Windows 多线程学习一
- 学习windows内核一
- 服务学习小记(一)
- 分布式服务--dubbo学习一
- Windows服务编写原理及探讨(一)
- Windows服务编写原理及探讨(一)
- delphi操作windows COM+组件服务一
- Windows服务编写原理及探讨(一)
- 人生杂谈(持续更新~)
- 键盘维护
- Ubuntu挂起,杯具了。
- 社会杂谈(持续更新~)
- 如果你到了20岁,还没到 25岁 作者:李开复
- Windows服务学习一
- 一年了,我现在又回到学习VB的路上了
- CMD外部命令
- 我谈搜索引擎
- E语言教程初期教程
- 61条面向对象设计的经验原则 [zz]
- jQuery指南/基础片
- 不安全代码只会在使用 /unsafe 编译的情况下出现
- 劣质VGA线导致不支持非标准分辨率显示