编写windows服务程序
2012-11-02 08:54 (分类:计算机程序)
windows服务是一个运行在后台并实现勿需用户交互的任务的控制台程序,对于隐藏程序有很大帮助。
用了几天时间概括了编写windows服务程序的轮廓,下面用伪码记录一下。
//两个全局变量
SERVICE_STATUS_HANDLE StatusHandle
SERVICE_STATUS m_ServiceStatus
void main()
{
//一个程序可能包含若干个服务。每一个服务都必须列于专门的分派表中
SERVICE_TABLE_ENTRY ServiceTable[2]; //结构类型的数组,
ServiceTable[0].lpServiceName = "MemoryStatus"; //服务名
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain; //服务主函数
ServiceTable[1].lpServiceName = NULL; //数组最后一个成员组默认都为NULL
ServiceTable[1].lpServiceProc = NULL;
// 启动服务的控制分派机线程, 负责把程序主线程连接到服务控制管理程序SCM,通知服务控制程序//服务正在执行,并提供函数地址;为每一个传递到它的数组中的非空元素产生一个新的线程,每一//个进程开始执行由数组元素中的指明的ServiceMain函数;SCM启动一个服务程序之后,它会等待该/*程序的主线程去调StartServiceCtrlDispatcher。如果那个函数在两分钟内没有被调用,SCM将会认为这个服务有问题,并调用TerminateProcess去杀死这个进程。这就要求你的主线程要尽可能快的调用StartServiceCtrlDispatcher,开始启动服务解析*/
StartServiceCtrlDispatcher(ServiceTable);
}
ServiceMain 函数
该函数是服务的入口点。它运行在一个单独的线程当中,这个线程是由控制分派器创建的。ServiceMain 应该尽可能早早为服务注册控制处理器
void WINAPI ServiceMain()
{
//指定服务特征和其当前状态来初始化 ServiceStatus 结构
m_ServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
//指示服务类型,创建 Win32 服务。赋值 SERVICE_WIN32;
m_ServiceStatus.dwCurrentState=SERVICE_START_PENDING;
//指定服务的当前状态。因为服务的初始化在这里没有完成,所以这里 状态为SERVICE_START_PENDING;
m_ServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN
//这个域通知 SCM 服务接受哪个域,停止,关机停止
m_ServiceStatus.dwWin32ExitCode=0; //是允许服务报告错误的关键
m_ServiceStatus.dwServiceSpecificExitCode=0; //一般不关心,设为0
m_ServiceStatus.dwCheckPoint=0; //是一个服务用来报告它当前的事件进展情况的
m_ServiceStatus.dwWaitHint=0; //一般不关心,设为0
//使用API函数RegisterServiceCtrlHandler()设置服务控制管理器SCM的服务控制处理函数
//ServiceMain 应该尽可能早早为服务注册控制处理器(尽量1秒之内)。这要通过调用 //RegisterServiceCtrlHadler 函数来实现;调用RegisterServiceCtrlHandler函数去通知SCM //它的CtrlHandler回调函数的地址
//SERVICE_STATUS_HANDLE StatusHandle是一个全局变量,当需要改变状态时 //SetServiceStatus()用它来标识一个服务。
SERVICE_STATUS_HANDLE StatusHandle
StatusHandle =RegisterServiceCtrlHadler("system",serviceCtrlHandler) //函数名称 //控制函数CtrlHandler函数地址
//RegisterServiceCtrlHandler返回一个SERVICE_STATUS_HANDLE,这是一个32位的句柄。SCM用 //它来唯一确定这个服务。当这个服务需要把它当时的状态报告给SCM的时候,就必须把这个句柄传//给需要它的Win32函数
//在RegisterServiceCtrlHandler函数返回后,ServiceMain线程要立即告诉SCM服务正在继续初始//化。具体的方法是通过调用SetServiceStatus函数传递SERVICE_STATUS数据结构。
//通过调用 SetServiceStatus 函数,用 hStatus 向 SCM 报告服务的状态。
//一旦服务被完全初始化,就应该重新初始化SERVICE_STATUS结构的成员,更改dwCurrentState //为SERVICE_RUNNING,然后把dwCheckPoint和dwWaitHint都改为0,将状态及时通告给服务控制管 //理器SCM,使用一个API函数SetServiceStatus()来实现这一目标
m_ServiceStatus.dwCurrentState=SERVICE_START_RUNNING;
m_ServiceStatus.dwCheckPoint=0;
m_ServiceStatus.dwWaitHint=0;
SetServiceStatus(StatusHandle,m_ServiceStatus )
//服务的句柄 //SERVICE_STATUS结构的地址
door();启动后门程序
return;
}
void WINAPI ServiceCtrlHandler(DWORD dwControl) //服务控制函数
{
switch (dwControl)
{
case SERVICE_CONTROL_PAUSE:
servicestatus.dwCurrentState = SERVICE_PAUSE_PENDING;
// TODO: add code to set dwCheckPoint & dwWaitHint
// This value need to try a lot to confirm
// ...
SetServiceStatus(servicestatushandle, &servicestatus);
// TODO: add code to pause the service
// not called in this service
// ...
servicestatus.dwCurrentState = SERVICE_PAUSED;
// TODO: add code to set dwCheckPoint & dwWaitHint to 0
break;
case SERVICE_CONTROL_CONTINUE:
servicestatus.dwCurrentState = SERVICE_CONTINUE_PENDING;
// TODO: add code to set dwCheckPoint & dwWaitHint
SetServiceStatus(servicestatushandle, &servicestatus);
// TODO: add code to unpause the service
// not called in this service
// ...
servicestatus.dwCurrentState = SERVICE_RUNNING;
// TODO: add code to set dwCheckPoint & dwWaitHint to 0
break;
case SERVICE_CONTROL_STOP:
servicestatus.dwCurrentState = SERVICE_STOP_PENDING;
// TODO: add code to set dwCheckPoint & dwWaitHint
SetServiceStatus(servicestatushandle, &servicestatus);
// TODO: add code to stop the service
Stop();
servicestatus.dwCurrentState = SERVICE_STOPPED;
// TODO: add code to set dwCheckPoint & dwWaitHint to 0
break;
case SERVICE_CONTROL_SHUTDOWN:
// TODO: add code for system shutdown
// as quick as possible
break;
case SERVICE_CONTROL_INTERROGATE:
// TODO: add code to set the service status
// ...
servicestatus.dwCurrentState = SERVICE_RUNNING;
break;
}
SetServiceStatus(servicestatushandle, &servicestatus);
}
//安装服务函数
//OpenSCManager函数是在创建一个服务对象(CreateService),并且把它加入到中要调用的API
//打开服务管理数据库
SC_HANDLE schService;
SC_HANDLE schSCManager;
schSCManager=OpenSCManager(
NULL, //本地计算机
NULL, //默认的数据库
SC_MANAGER_ALL_ACCESS //要求所有的访问权
);
//创建进程
CreateService(
SC_HANDLE hSCManager,//服务控制管理程序维护的登记数据库的句柄,由系统函数 OpenSCManager 返回
LPCTSTR lpServiceName, //以NULL 结尾的服务名,用于创建登记数据库中的关键字
LPCTSTR lpDisplayName, //以NULL 结尾的服务名,用于用户界面标识服务
DWORD dwDesiredAccess, //指定服务返回类型
DWORD dwServiceType, //指定服务类型
DWORD dwStartType, //指定何时启动服务
DWORD dwErrorControl, //指定服务启动失败的严重程度
LPCTSTR lpBinaryPathName, //指定服务程序二进制文件的路径
LPCTSTR lpLoadOrderGroup, //指定顺序装入的服务组名
LPDWORD lpdwTagId, //忽略,NULL
LPCTSTR lpDependencies, //指定启动该服务前必须先启动的服务或服务组
LPCTSTR lpServiceStartName, //以NULL 结尾的字符串,指定服务帐号。如是NULL,则表示使用 LocalSystem 帐号
LPCTSTR lpPassword //以NULL 结尾的字符串,指定对应的口令。为NULL表示无口。 但使用LocalSystem时填NULL
schService=CreateService(
schSCManager, //服务管理数据库句柄
TEXT(SZSERVICENAME), //服务名
TEXT(SZAPPNAME), //用于显示服务的标识
SERVICE_ALL_ACCESS, //响应所有的访问请求
SERVICE_WIN32_OWN_PROCESS, //服务类型
SERVICE_DEMAND_START, //启动类型
SERVICE_ERROR_NORMAL, //错误控制类型
szPath, //服务程序磁盘文件的路径
NULL, //服务不属于任何组
NULL, //没有tag标识符
NULL, //启动服务所依赖的服务或服务组,这里仅仅是一个空字符串
NULL, //LocalSystem 帐号
NULL);
删除服务时调用
DeleteService;它只有一个参数(服务句柄)。我们可分四步完成
1)、打开SCM句柄。
2)、打开要删除的服务。
3)、检查当前服务的状态确保服务已经停止。
4)、删除服务并关闭所有打开的句柄。下面是一段删除服务的程序。
SC_HANDLE Service,scm;
SERVICE_STATUS status;
BOOL success;
scm = OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE); //打开SCM句柄。
//打开要删除的服务
Service = OpenService(scm,pszServiceName,SERVICE_ALL_ACCESS|DELETE);
//检查当前服务的状态确保服务已经停止
if (!Service){
cout<<"OpenService ERROR:"<<GetLastError()<<endl;
CloseServiceHandle(Service);
CloseServiceHandle(scm);
return false;
}
success = QueryServiceStatus(Service,&status);
if (!success){
cout<<"QueryServiceStatus ERROR:"<<GetLastError()<<endl;
CloseServiceHandle(Service);
CloseServiceHandle(scm);
return false;
}
if (status.dwCurrentState!=SERVICE_STOPPED)
{
success = ControlService(Service,SERVICE_CONTROL_STOP,&status);
if (!success){
cout<<"ControlService ERROR:"<<GetLastError()<<endl;
CloseServiceHandle(Service);
CloseServiceHandle(scm);
return false;
}
}
//删除服务
success = DeleteService(Service);
if (!success){
cout<<"DeleteService ERROR:"<<GetLastError()<<endl;
CloseServiceHandle(Service);
CloseServiceHandle(scm);
return false;
}
bb//关闭所有打开的句柄
CloseServiceHandle(Service);
CloseServiceHandle(scm);
return true;
编写windows服务程序的更多相关文章
- C语言编写Windows服务程序
原文:C语言编写Windows服务程序 #include <Windows.h> #include <stdio.h> #define SLEEP_TIME 5000 // 间 ...
- 用 C 语言编写 Windows 服务程序的五个步骤
Windows 服务被设计用于需要在后台运行的应用程序以及实现没有用户交互的任务.为了学习这种控制台应用程序的基础知识,C(不是C++)是最佳选择.本文将建立并实现一个简单的服务程序,其功能是查询系统 ...
- 用C语言编写Windows服务程序的五个步骤
Windows 服务被设计用于需要在后台运行的应用程序以及实现没有用户交互的任务.为了学习这种控制台应用程序的基础知识,C(不是C++)是最佳选择.本文将建立并实现一个简单的服务程序,其功能是查询系统 ...
- Python3编写Windows服务程序
最近做了公司签到的小工具,有同事要求做成Windows服务,开机自启.先说下怎么用Python写Windows服务程序. #encoding=utf-8 import win32serviceutil ...
- C#编写Windows服务程序图文教程
安装服务程序C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe 要安装的服务程序路径(如F:\***.exe)卸载服务程序C: ...
- C#编写Windows服务程序 (服务端),client使用 消息队列 实现淘宝 订单全链路效果
需求: 针对 淘宝提出的 订单全链路 产品接入 .http://open.taobao.com/doc/detail.htm?id=102423&qq-pf-to=pcqq.group oms ...
- C#编写windows服务程序
Windows Service这一块并不复杂,但是注意事项太多了,网上资料也很凌乱,偶尔自己写也会丢三落四的.所以本文也就产生了,本文不会写复杂的东西,完全以基础应用的需求来写,所以不会对Window ...
- C#编写Windows服务程序图文教程(转载)
Windows Service这一块并不复杂,但是注意事项太多了,网上资料也很凌乱,偶尔自己写也会丢三落四的.所以本文也就产生了,本文不会写复杂的东西,完全以基础应用的需求来写,所以不会对Window ...
- 用Visual C#创建Windows服务程序
一.Windows服务介绍: Windows服务以前被称作NT服务,是一些运行在Windows NT.Windows 2000和Windows XP等操作系统下用户环境以外的程序.在以前,编写Wind ...
随机推荐
- BigDecimal的加减乘除,比较,小数保留
关于BigDecimal的一些常用基本操作记录 1 BigDecimal b1 = new BigDecimal("1.124"); 2 BigDeci ...
- STL 结构体内重载 一个比较运算符
struct node { ll a, b; bool operator< (const node &c)const{ return a < c.a; } }pre[eps];
- SpringSecurity 初始化流程源码
SpringSecurity 初始化流程源码 本篇主要讲解 SpringSecurity初始化流程的源码部分,包括核心的 springSecurityFilterChain 是如何创建的,以及在介绍哪 ...
- 《C# 爬虫 破境之道》:概述
第一节:写作本书的目的 关于笔者 张晓亭(Mike Cheers),1982年出生,内蒙古辽阔的大草原是我的故乡. 没有高学历,没有侃侃而谈的高谈阔论,拥有的就是那一份对技术的执著,对自我价值的追求. ...
- python 进程信号量
1.概念 信号量和锁相似,锁同一时间只允许一个对象(进程)通过,信号量同一时间允许多个对象(进程)通过 2.应用场景 多线程,并规定数量 3.格式: 导入信号量模块 实例化信号量对象,可以规定信号量的 ...
- 关于SpringDataJpa中测试出现StackOverflowError错误问题
在使用SpringDataJpa进行多表查询时,使用导航查询,每次都出现 StackOverflowError错误, 经过查找资料,网上百度,终于找到原因, StackOverflowError 是栈 ...
- Linux下Tomcat,mysql安装包及教程整合,
前段时间孔老师给了一个虚拟机,自己瞎捣鼓,装了Tomcat和mysql,捣鼓了好几天,把一些安装包和试过还不错的博客整理出来: 老师给的已经装好了Linux系统和JDK. Tomcat9安装包 ...
- Collections中的常用方法
collections中的常用方法 public class CollectionsTest { public static void main(String[] args) { List list ...
- 「 从0到1学习微服务SpringCloud 」01 一起来学呀!
有想学微服务的小伙伴没?一起来从0开始学习微服务SpringCloud,我会把学习成果总结下来,供大家参考学习,有兴趣可以一起来学!如有错误,望指正! Spring .SpringBoot.Sprin ...
- nuxt.js学习初探
项目目标 把我个人博客的前端界面部分使用nuxt框架进行服务端渲染 nuxt介绍 nuxt可以把spa根据路由将单页面分割成多页面,比起vue的ssr渲染要更容易使用 nuxt的使用 项目创建 npx ...