WIN32服务程序(三):完整的服务程序实例
前面我们所讲的“服务程序”,更准确地说是服务控制程序,例如我们通过输入应用的路径,将一个应用程序添加到服务控制管理器。一个服务控制程序可以将一个程序添加到服务控制管理器中,并控制它的运行、停止和删除等。那么怎么避免手动添加的方式,直接将我们想要运行的代码添加到服务中呢?这需要我们建立一个完整的服务程序,要同时包括服务主程序和服务控制程序。
关于服务主程序
服务主程序包括一个main函数作为程序的标准入口,一个ServiceMain函数作为服务程序的入口,一个Handler函数实现服务启动,停止等功能,最后是一个MyWork函数,这里面可以写入我们想要运行的代码,也就是服务要实现的功能。
我们来看一个程序,该程序实现的功能是在服务运行期间,循环执行MessageBox函数;可以在cmd上运行应用程序,给其传递参数,实现对于服务的控制。这个程序在逻辑的实现上比较简单,某些函数可以直接查看msdn文档,附上链接地址https://technet.microsoft.com/zh-cn/library/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsvc.h>
#include <stdio.h> #define SLEEP_TIME 5000
#define LOG_FILE "c:\\MemoryWatch.txt"
#define SERVICE_NAME "servitest"
#define SERVICE_DESC "test"
#define SERVICE_DISPLAY_NAME "test" SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
SC_HANDLE scm;
SC_HANDLE scv; void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
void Log(char* filename);
int startFunc();
void OnStart();
void OnCreate();
void OnDelete();
void OnStop(); int main(int argc, char* argv[])
{
// Service Name:MemoryStatus
// Service Handle Function: ServiceMain()
SERVICE_TABLE_ENTRY ServiceTable[] =
{ { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain }, { NULL,NULL}
}; if(argc == )
{
if(!stricmp(argv[],"-create"))
{
OnCreate();
return ;
}
else if(!stricmp(argv[],"-delete"))
{
OnDelete();
return ;
}
else if(!stricmp(argv[],"-start"))
{
OnStart();
return ;
}
else if(!stricmp(argv[],"-stop"))
{
OnStop();
return ;
}
else
{
printf("invailid parameter\n");
return ;
}
} StartServiceCtrlDispatcher(ServiceTable);
return ;
} void Log(char* str)
{
FILE* fp = fopen(LOG_FILE, "a+");
if(fp == NULL)
{
printf("error to open file: %d\n", GetLastError());
return;
} fprintf(fp, "%s\n", str);
fflush(fp);
fclose(fp);
} void ServiceMain(int argc, char** argv)
{
BOOL bRet;
int result; bRet = TRUE; ServiceStatus.dwWin32ExitCode = ;
ServiceStatus.dwCheckPoint = ;
ServiceStatus.dwWaitHint = ;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwServiceSpecificExitCode = ; hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)ControlHandler);
if(hStatus == (SERVICE_STATUS_HANDLE))
{
// log failed
return;
}
//service status update
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &ServiceStatus); while(ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
result = startFunc();
if(result)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
}
} int startFunc()
{
MessageBox(NULL, "startFunc", SERVICE_NAME, MB_OK);
return ;
} void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
Log("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = ;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return; case SERVICE_CONTROL_SHUTDOWN:
Log("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = ;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
} SetServiceStatus (hStatus, &ServiceStatus);
} void OnCreate()
{
char filename[MAX_PATH];
DWORD dwErrorCode;
GetModuleFileName(NULL, filename, MAX_PATH);
printf("Creating Service .... ");
scm = OpenSCManager(/*localhost*/,
NULL/*SERVICES_ACTIVE_DATABASE*/,
SC_MANAGER_ALL_ACCESS/*ACCESS*/);
if (scm == NULL)
{
printf("OpenSCManager error:%d\n", GetLastError());
return;
}
scv = CreateService(scm,//句柄
SERVICE_NAME,//服务开始名
SERVICE_DISPLAY_NAME,//显示服务名
SERVICE_ALL_ACCESS, //服务访问类型
SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,//服务类型
SERVICE_AUTO_START, //自动启动服务
SERVICE_ERROR_IGNORE,//忽略错误
filename,//启动的文件名
NULL,//name of load ordering group (载入组名)
NULL,//标签标识符
NULL,//相关性数组名
NULL,//帐户(当前)
NULL); //密码(当前) if (scv == NULL)
{
dwErrorCode = GetLastError();
if(dwErrorCode!=ERROR_SERVICE_EXISTS)
{
printf("Failure !\n");
CloseServiceHandle(scm);
return ;
}
else
{
printf("already Exists !\n");
}
}
else
{
printf("Success !\n");
CloseServiceHandle(scv); } CloseServiceHandle(scm);
scm = scv = NULL;
} void OnDelete()
{
scm=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (scm!=NULL)
{
scv=OpenService(scm,SERVICE_NAME,SERVICE_ALL_ACCESS);
if (scv != NULL)
{
QueryServiceStatus(scv,&ServiceStatus);
if (ServiceStatus.dwCurrentState==SERVICE_RUNNING)
{
ControlService(scv,SERVICE_CONTROL_STOP,&ServiceStatus);
}
DeleteService(scv);
CloseServiceHandle(scv);
}
CloseServiceHandle(scm);
}
scm = scv = NULL;
} void OnStart()
{
DWORD dwErrorCode;
//Starting Service
printf("Starting Service .... ");
scm = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(scm != NULL)
{
scv = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
if (scv != NULL)
{
if(StartService(scv, , NULL)==)
{
dwErrorCode = GetLastError();
if(dwErrorCode == ERROR_SERVICE_ALREADY_RUNNING)
{
printf("already Running !\n");
CloseServiceHandle(scv);
CloseServiceHandle(scm);
return ;
}
}
else
{
printf("Pending ... ");
} //wait until the servics started
while(QueryServiceStatus(scv,&ServiceStatus)!=)
{
if(ServiceStatus.dwCurrentState == SERVICE_START_PENDING)
{
Sleep(); }
else
{
break; }
} CloseServiceHandle(scv);
}
else
{
//error to OpenService
printf("error to OpenService\n");
} CloseServiceHandle(scm);
}
else
{
//fail to OpenSCManager
}
/*
if(InstallServiceStatus.dwCurrentState != SERVICE_RUNNING)
{
printf("Failure !\n");
}
else
{
printf("Success !\nDumping Description to Registry...\n");
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\NtBoot",
0,
KEY_ALL_ACCESS,
&hkResult);
RegSetValueEx(hkResult,
"Description",
0,
REG_SZ,
(unsigned char *)"Driver Booting Service",
23); RegCloseKey(hkResult);
} CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);
}//
*/ scm = scv = NULL;
} void OnStop()
{
scm = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(scm != NULL)
{
scv = OpenService(scm,SERVICE_NAME,SERVICE_STOP | SERVICE_QUERY_STATUS);
if (scv!=NULL)
{
QueryServiceStatus(scv,&ServiceStatus);
if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
ControlService(scv,SERVICE_CONTROL_STOP,&ServiceStatus);
}
CloseServiceHandle(scv);
}
CloseServiceHandle(scm);
}
scm = scv = NULL;
}
程序编译好之后,运行cmd。我编译好的程序的完整路径是 C:\hi\Debug\hi.exe
执行 C:\hi\Debug\hi.exe -create创建服务
执行C:\hi\Debug\hi.exe -start 启动服务
……
在c盘MemoryWatch.txt有日志文件
WIN32服务程序(三):完整的服务程序实例的更多相关文章
- MySQL基准测试(三)--开源工具与实例演示
MySQL基准测试(三)--开源工具与实例演示 针对web应用 ab ab是一个Apache HTTP服务的基准测试工具. http_load http_load是一个针对Web服务器测试工具. JM ...
- PHP 表单 - 5(完整表单实例)
PHP 完整表单实例 本章节将介绍如何让用户在点击"提交(submit)"按钮提交数据前保证所有字段正确输入. PHP - 在表单中确保输入值 在用户点击提交按钮后,为确保字段值是 ...
- grpc使用记录(三)简单异步服务实例
目录 grpc使用记录(三)简单异步服务实例 1.编写proto文件,定义服务 2.编译proto文件,生成代码 3.编写服务端代码 async_service.cpp async_service2. ...
- Nginx 笔记(三)nginx 配置实例 - 反向代理、负载均衡、动静分离
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.反向代理 反向代理准备工作: (1)在 liunx 系统安装 tomcat,使用默认端口 8080 ...
- ZYNQ SGI、PPI、SPI三种中断的实例(含代码)
ZYNQ中断分为3类: SGI(Software Generated Interrupts)软件中断 PPI(Private Peripheral Interrupts)私有外设中断 SPI(Shar ...
- C#最简单最完整的webservice实例
http://fyinthesky.blog.163.com/blog/static/3555251720110115227337/ 我做java,但最近接触crm所以必须研究一下C#中的webser ...
- 完整的Ajax实例
写在前面的话: 用了很久的Asp.Net Ajax,也看了段时间的jquery中ajax的应用,但到头来,居然想不起xmlHttpRequest的该如何使用了. 以前记的也不怎么清楚,这次就重新完整的 ...
- JS创建事件的三种方式(实例)
1.普通的定义方式 <input type="button" name="Button" value="确定" onclick=&qu ...
- Android Studio 一个完整的APP实例(附源码和数据库)
前言: 这是我独立做的第一个APP,是一个记账本APP. This is the first APP, I've ever done on my own. It's a accountbook APP ...
随机推荐
- OC基础--构造方法 id类型
new方法实现原理: new做了三件事情 1.开辟存储空间 + alloc 方法 2.初始化所有的属性(成员变量) - init 方法 3.返回对象的地址 [Person new]; == [[Pe ...
- 【初级】linux pwd 命令详解及使用方法实战
pwd:查看当前工作目录 前言: Linux中用 pwd 命令来查看”当前工作目录“的完整路径,就是经常提及的所在目录,多用在生产环境多级目录中查看当前所在路径,使用此命令能给运维人员/操作人员带来很 ...
- AAS代码第2章
[root@node1 aas]# pwd /root/aas [root@node1 aas]# wget http://archive.apache.org/dist/spark/spark-1. ...
- ArcEngine拓扑
空间拓扑描述的是自然界地理对象的空间位置关系-相邻,重合,连通等,是地理对象空间属性的一部分.目前ESRI提供的数据存储方式中,Coverage和GeoDatabase能够建立拓扑,Shape格式的数 ...
- React学习笔记
1.React的一开始出发点是:用于开发数据不断变化的大型应用程序(Building large applications with data that changes over time) 2.生命 ...
- 自定义cell(xib)中button点击事件不能响应的情况
遇到这种问题真的好尴尬,之前从来没有遇到过,以为手到擒来,未曾料到还会遇到问题! 好多年没有找到尴尬的感觉,现在找到了,真的很尴尬 ! *o* 1.首先使用场景: 原本没打算用xib,后来为了快速, ...
- MFC 对话框控件自动布局
MFC 设计界面程序总是不够智能,没有这样,没有那样. 今天为了加强mfc功能,设计了一个自动布局的类,使用非常简单. 原理: 每个控件都有一个矩形区域,矩形区域就是控件在对话框中的显示位置和大小, ...
- python2.7安装scikit-learn遇到的问题及解决方法
安装完matplotlib后,在运行scikit-learn相关的库的时候又遇到缺包的问题,本来以为缺什么包就装什么包,但是由于种种原因,使我走上了弯路: 第一个坑:学校校园网限制.我用scikit- ...
- AngularJS身份验证:Cookies VS Tokens
基于cookie的身份验证:Cookie-Based Authentication 基于token的身份验证:Token-Based Authentication 跨域:cross-domain 说明 ...
- Fragment的使用(一)
本篇博客主要讲的是如何使用Fragment. 使用Fragment的步骤类似于自定义View的步骤: 定义Fragment的布局文件 实现扩展Fragment的子类 在扩展子类的onCreateVie ...