前面我们所讲的“服务程序”,更准确地说是服务控制程序,例如我们通过输入应用的路径,将一个应用程序添加到服务控制管理器。一个服务控制程序可以将一个程序添加到服务控制管理器中,并控制它的运行、停止和删除等。那么怎么避免手动添加的方式,直接将我们想要运行的代码添加到服务中呢?这需要我们建立一个完整的服务程序,要同时包括服务主程序和服务控制程序。

关于服务主程序

服务主程序包括一个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服务程序(三):完整的服务程序实例的更多相关文章

  1. MySQL基准测试(三)--开源工具与实例演示

    MySQL基准测试(三)--开源工具与实例演示 针对web应用 ab ab是一个Apache HTTP服务的基准测试工具. http_load http_load是一个针对Web服务器测试工具. JM ...

  2. PHP 表单 - 5(完整表单实例)

    PHP 完整表单实例 本章节将介绍如何让用户在点击"提交(submit)"按钮提交数据前保证所有字段正确输入. PHP - 在表单中确保输入值 在用户点击提交按钮后,为确保字段值是 ...

  3. grpc使用记录(三)简单异步服务实例

    目录 grpc使用记录(三)简单异步服务实例 1.编写proto文件,定义服务 2.编译proto文件,生成代码 3.编写服务端代码 async_service.cpp async_service2. ...

  4. Nginx 笔记(三)nginx 配置实例 - 反向代理、负载均衡、动静分离

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.反向代理 反向代理准备工作: (1)在 liunx 系统安装 tomcat,使用默认端口 8080 ...

  5. ZYNQ SGI、PPI、SPI三种中断的实例(含代码)

    ZYNQ中断分为3类: SGI(Software Generated Interrupts)软件中断 PPI(Private Peripheral Interrupts)私有外设中断 SPI(Shar ...

  6. C#最简单最完整的webservice实例

    http://fyinthesky.blog.163.com/blog/static/3555251720110115227337/ 我做java,但最近接触crm所以必须研究一下C#中的webser ...

  7. 完整的Ajax实例

    写在前面的话: 用了很久的Asp.Net Ajax,也看了段时间的jquery中ajax的应用,但到头来,居然想不起xmlHttpRequest的该如何使用了. 以前记的也不怎么清楚,这次就重新完整的 ...

  8. JS创建事件的三种方式(实例)

    1.普通的定义方式 <input type="button" name="Button" value="确定" onclick=&qu ...

  9. Android Studio 一个完整的APP实例(附源码和数据库)

    前言: 这是我独立做的第一个APP,是一个记账本APP. This is the first APP, I've ever done on my own. It's a accountbook APP ...

随机推荐

  1. CSS3让一段文字多余的用省略号表示,当鼠标移动上去的时候显示全部文字

    <style type="text/css"> div { width:100px; overflow:hidden; white-space:nowrap; text ...

  2. asp.net网站运行出错:the underlying provider failed on open的解决

    在登录系统,通过linq查询时发生错误,the underlying provider failed on open,如何解决,请看: Step 1:Open Internet Information ...

  3. Java 入门(一) - 环境变量

    Win 7 X64环境 计算机(右键)-> 属性 -> 高级系统设置 -> 环境变量1.新建系统变量 : JAVA_HOME C:\Program Files (x86)\Java\ ...

  4. bzoj 3211: 花神游历各国

    #include<cstdio> #include<cmath> #include<iostream> #define M 100006 using namespa ...

  5. 封装获取dom元素

    <script> //函数: 反复执行的代码块 //全局只有一个对象,防止全局变量污染 var itcast = { getElen : { tag : function(tag){ re ...

  6. Visor 应用之一 通过ER 设计生成数据库脚本和实体对象

    前言 Visor(http://www.visor.com.cn)   是一个基于HTML5 Canvas 开发的IDE 框架和设计开发平台,有关Visor的设计架构和技术应用,在以后的文章里会逐渐跟 ...

  7. 在CDH5.5.0上安装Kudu6.0

    1. 下载安装文件: a. CSD文件:KUDU-0.6.0.jar b. kudu parcel:KUDU-0.6.0-1.kudu0.6.0.p0.334-el6.parcel和manifest. ...

  8. hdu 1159, LCS, dynamic programming, recursive backtrack vs iterative backtrack vs incremental, C++ 分类: hdoj 2015-07-10 04:14 112人阅读 评论(0) 收藏

    thanks prof. Abhiram Ranade for his vedio on Longest Common Subsequence 's back track search view in ...

  9. Java特性-Collection和Map

    创建博客的目的主要帮助自己记忆和复习日常学到和用到的知识:或有纰漏请大家斧正,非常感谢! 之前面试,被问过一个问题:List和Set的区别. 主要区别很明显了,两者都是数组形式存在的,继承了Colle ...

  10. Windows Server 2003 IIS6.0+PHP5(FastCGI)+MySQL5环境搭建教程

    准备篇 一.环境说明: 操作系统:Windows Server 2003 SP2 32位 PHP版本:php 5.3.14(我用的php 5.3.10安装版) MySQL版本:MySQL5.5.25 ...