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

关于服务主程序

服务主程序包括一个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. java 文件按行读取

    /*代码写的可能有点累赘里面的好多东西写的不太好 还望各位大佬能提点一二,不胜感激*/package com.zzp.fileopration;import java.io.*;/** * Creat ...

  2. python爬取数据保存入库

    import urllib2 import re import MySQLdb class LatestTest: #初始化 def __init__(self): self.url="ht ...

  3. 金山软件wps2012-2013通杀0day

    #!/usr/bin/python # Exploit Title: Kingsoft Office Writer v2012 8.1.0.3385 .wps Buffer Overflow Expl ...

  4. μC/OS-Ⅲ中的临界段代码

    临界段代码(critical sections),也叫临界区(critical region),是指那些必须完整连续运行,不可被打断的代码段.μC/OS-Ⅲ系统中存在大量临界段代码.采用两种方式对临界 ...

  5. ubuntu 使用中的一些问题汇总

    1.IOError: [Errno 13] Permission denied /usr/local…… 这个错误是在terminal中运行pip install 时产生的,说的时没有权限运行安装包, ...

  6. XML特殊字符处理

    XML共有5个特殊字符,分别为:&<>"' 如果XML文件中需要包含如上5个特殊字符,有两种方式: 1.将包含特殊字符的字符串放在<![CDATA[]]>中 ...

  7. Ant介绍

    今天介绍一下Ant,Ant是基于Java的跨平台构建工具,它易于使用,并且可扩展.可升级.它既可以用于小的个人项目,也可以用于大型的.多组协同的软件项目. 在我们的项目开发中,为了构建一个软件产品,我 ...

  8. 在iis7上如何配置来看到asp报错

    今天网站改版时碰到一个问题,客户要求老网站的地图等功能要保持,但是老网站是用asp开发的.我们可以直接利用老的数据库以及老的代码,但是部署到新的服务器上一直报错. 刚开始是404,后来是500...今 ...

  9. AngularJs的UI组件ui-Bootstrap分享(一)

    最近几个月学习了AngularJs和扩展的UI组件,并在公司小组内做了一次分享交流,感觉很有收获,在此记录下个人的学习心得. 目录: AngularJs的UI组件ui-Bootstrap分享(一) A ...

  10. 例子:Background Transfer Service Sample

    本例演示了如何使用后台传输服务来进行后台文件下载,也就是说及时App已经停止运行,同样可以通过后台代理进行文件的下载操作. 对于后台文件传输一下知识点必须注意: 1. 通过使用 BackgroundT ...