windows服务的简单实现(原创)
2010-10-21 13:39
483 查看
WINDOWS编程,可以使用命令行方式的,也可以使用图形界面方式的。可有一种程序它没有命令行输出,也没有图形界面。例如,实现IP功能的程序,实现DNS的程序,系统驱动,服务器程序等,他们都没有界面,也没有命令行输出。它们长期运行于内存,大部分时间处于睡眠状态,等某个操作触发了某个相关事件,它们便开始运行。要实现这样一类程序,那么必须用到WINDOWS服务了。打开控制面板-管理工具-服务,就可以看到当前系统中所有的服务。你可以停止它,可以设置开机启动等。我们不禁想问,既然有这个功能,那么怎么实现我们自己的服务呢?就我两天来查阅到的资料,我简单的讲讲WINDOWS服务的初步实现。还是那句话,如有纰漏,请务必指正。
如果直接给出代码,我想还是比较晕的。那我先来讲讲服务的运行过程。我就按照事件的发生顺序大概讲下。我先假设服务已经加载到系统中。在你开启服务的一瞬间,系统加载该服务的程序。是程序肯定要有主函数。所以服务的入口不可避免的也是int main(int argc,char **argv[]);。进入之后,先声明下服务的名称和启动句柄,说白了就是服务的入口函数,我们通常给它称作ServiceMain。然后用StartServiceCtrlDispatcher()函数,启动服务的入口函数。那么服务的入口函数中又发生了什么?首先是设置服务的启动状态,然后用RegisterServiceCtrlHandler()函数注册服务的控制函数,控制函数我们通常称作ServiceHandle。这样,服务的启动算是完成了。接下来就要设置服务的运行状态。设置完运行状态,紧接着就是这个服务的核心代码了,它到底要完成什么实际操作。大部分情况下,是设置一个循环,用来处理某事件的发生。或者设置一个调用句柄,用来设置系统发生一相关事件后的处理函数入口。到这里服务的主函数是写完了,你肯定有个疑问,怎么关闭服务呢?嗯,不要忘了我们刚刚用RegisterServiceCtrlHandler()函数注册服务的控制函数了。所以控制服务运行的内容肯定在服务的控制函数里。控制服务函数里有一个switch结构,用来判断服务要进行的操作。可以暂停,停止,重启等。
到这里一个服务就实现了。我也不多讲,我先给出网上的一个实例。很多国内的网站都有这个例子。我原以为是国内某个程序员写的。但当我到谷歌里一搜索,靠,还TM是老外写的。你说中国编程不行也就算了,连写个教程都不如人家。不过这个例子蛮经典,我就不拿自己的成果来现了。
//MemoryStatus.cpp
#include <windows.h>
#include <stdio.h>
#define SLEEP_TIME 5000
#define LOGFILE "C://MyServices//memstatus.txt"
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService();
int WriteToLog(char* str)
{
FILE* log;
log = fopen(LOGFILE, "a+");
if (log == NULL)
return -1;
fprintf(log, "%s/n", str);
fclose(log);
return 0;
}
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;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
}
void ServiceMain(int argc, char** argv)
{
int error;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandler(
"MemoryStatus",
(LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}
// Initialize Service
error = InitService();
if (error)
{
// Initialization failed
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// We report the running status to SCM.
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);
MEMORYSTATUS memory;
// The worker loop of a service
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
char buffer[16];
GlobalMemoryStatus(&memory);
sprintf(buffer, "%d", memory.dwAvailPhys);
int result = WriteToLog(buffer);
if (result)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
Sleep(SLEEP_TIME);
}
return;
}
// Service initialization
int InitService()
{
int result;
result = WriteToLog("Monitoring started.");
return(result);
}
// Control handler function
void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}
写着写着就忘了,回家路上突然想起来,光有这个是不能运行的。要在系统中注册写的这个服务。可以用sc.exe实现这个功能。每个系统基本都带这个工具。用sc create MemoryStatus d:/MemoryStatus.exe这个命令,来注册这个服务。用sc delete MemoryStatus来删除服务。然后打开控制面板-管理工具-服务,找到这个服务,启动。其实是可以用编程方式注册服务的。不过由于精力有限,我就不去琢磨了。
如果直接给出代码,我想还是比较晕的。那我先来讲讲服务的运行过程。我就按照事件的发生顺序大概讲下。我先假设服务已经加载到系统中。在你开启服务的一瞬间,系统加载该服务的程序。是程序肯定要有主函数。所以服务的入口不可避免的也是int main(int argc,char **argv[]);。进入之后,先声明下服务的名称和启动句柄,说白了就是服务的入口函数,我们通常给它称作ServiceMain。然后用StartServiceCtrlDispatcher()函数,启动服务的入口函数。那么服务的入口函数中又发生了什么?首先是设置服务的启动状态,然后用RegisterServiceCtrlHandler()函数注册服务的控制函数,控制函数我们通常称作ServiceHandle。这样,服务的启动算是完成了。接下来就要设置服务的运行状态。设置完运行状态,紧接着就是这个服务的核心代码了,它到底要完成什么实际操作。大部分情况下,是设置一个循环,用来处理某事件的发生。或者设置一个调用句柄,用来设置系统发生一相关事件后的处理函数入口。到这里服务的主函数是写完了,你肯定有个疑问,怎么关闭服务呢?嗯,不要忘了我们刚刚用RegisterServiceCtrlHandler()函数注册服务的控制函数了。所以控制服务运行的内容肯定在服务的控制函数里。控制服务函数里有一个switch结构,用来判断服务要进行的操作。可以暂停,停止,重启等。
到这里一个服务就实现了。我也不多讲,我先给出网上的一个实例。很多国内的网站都有这个例子。我原以为是国内某个程序员写的。但当我到谷歌里一搜索,靠,还TM是老外写的。你说中国编程不行也就算了,连写个教程都不如人家。不过这个例子蛮经典,我就不拿自己的成果来现了。
//MemoryStatus.cpp
#include <windows.h>
#include <stdio.h>
#define SLEEP_TIME 5000
#define LOGFILE "C://MyServices//memstatus.txt"
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService();
int WriteToLog(char* str)
{
FILE* log;
log = fopen(LOGFILE, "a+");
if (log == NULL)
return -1;
fprintf(log, "%s/n", str);
fclose(log);
return 0;
}
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;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
}
void ServiceMain(int argc, char** argv)
{
int error;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandler(
"MemoryStatus",
(LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}
// Initialize Service
error = InitService();
if (error)
{
// Initialization failed
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// We report the running status to SCM.
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);
MEMORYSTATUS memory;
// The worker loop of a service
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
char buffer[16];
GlobalMemoryStatus(&memory);
sprintf(buffer, "%d", memory.dwAvailPhys);
int result = WriteToLog(buffer);
if (result)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
Sleep(SLEEP_TIME);
}
return;
}
// Service initialization
int InitService()
{
int result;
result = WriteToLog("Monitoring started.");
return(result);
}
// Control handler function
void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}
写着写着就忘了,回家路上突然想起来,光有这个是不能运行的。要在系统中注册写的这个服务。可以用sc.exe实现这个功能。每个系统基本都带这个工具。用sc create MemoryStatus d:/MemoryStatus.exe这个命令,来注册这个服务。用sc delete MemoryStatus来删除服务。然后打开控制面板-管理工具-服务,找到这个服务,启动。其实是可以用编程方式注册服务的。不过由于精力有限,我就不去琢磨了。
相关文章推荐
- 【原创】javascript模板引擎的简单实现
- [原创]会议室管理模块的简单实现
- php求圆周率的简单实现方法[原创]_php技巧_脚本之家
- CI(CodeIgniter)简单统计访问人数实现方法 原创
- 简单实现Android顶部工具栏和底部工具栏(原创)
- 动态链接库的简单实现(原创)
- 常见内部排序算法 简单数组实现与分析(快速(偶原创partition函数,望众高手指正)、归并、希尔、插入、选择、冒泡)
- [非原创]纯VB6实现Windows服务
- [原创]Adobe Edge Animate1.0 --创建按钮及简单功能实现
- 城市公交查询算法的简单实现(原创)
- 【PHPExecl】PHP简单实现Execl的导入导出【原创】
- 【原创】TCP Socket 简单练习 --- 线程池实现并发服务器 分类: Linux --- 应用程序设计 2014-12-25 13:59 50人阅读 评论(0) 收藏
- C#开发Windows服务 附简单实例实现禁止QQ运行
- 【原创源码】(03):利用简单递归算法,实现文本匹配、翻译。
- (原创)简单 jQuery 插件让 Table 中的 Tr 实现光棒效果
- 简单的屏幕弹幕功能的实现(原创)
- 简单3步 js使用cookie实现的购物车功能[原创]
- Java实现简单的计算器(原创)
- 【原创】ORACLE的几个函数在MYSQL里面的简单实现
- 简单实现负载均衡(原创)