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

关于服务主程序

服务主程序包括一个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. [暴力搜索] POJ 3087 Shuffle'm Up

    Shuffle'm Up Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10003   Accepted: 4631 Des ...

  2. Win7搭建nginx+php+mysql开发环境以及websocket聊天实例测试

    Win7搭建nginx+php+mysql开发环境以及websocket聊天实例测试一.下载相关安装包 1.下载nginx最新版本(nginx1.3.13版之后才支持websocket协议) 下载地址 ...

  3. C# 进程和线程

    一.进程和线程 进程是对一段静态指令序列的动态执行过程,是系统进行资源分配和调度的基本单位.与进程相关的信息包括进程的用户标志.正在执行的已经编译好的程序.程序和数据在存储器中的位置等.同一个进程有可 ...

  4. 专家解读:BPM与OA的区别

    演进历程 传统OA 模块化架构,仅能满足管理执行的刚性效率,系统的专业化程度有限. BPM 平台化架构,管理要求精细化程度高,系统更专业化,更注重整合. BPM SAAS 基于云架构,跨组织社交化,系 ...

  5. GitLab在Centos下的安装步骤

    第一步:(安装工具包) sudo yum install curl openssh-server postfix cronie sudo service postfix start sudo chkc ...

  6. UITableViewCell

    #import "ContactListTableViewController.h" #import "Contact.h" #import "Con ...

  7. js动画之平抛运动

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. stella mccartney falabella foldover tote a few eye observed

    Lately, the particular Heyuan City Courtroom retrial, in order to commit the criminal offense of cou ...

  9. TortoiseSVN文件夹及文件图标不显示解决方法

              由于自己的电脑是win7(64位)的,系统安装TortoiseSVN之后,其他的功能都能正常的使用,但是就是文件夹或文件夹的左下角就是不显示图标,这个问题前一段时间就遇到了(那个时 ...

  10. x-forward-for详解

    转载:http://www.360doc.com/content/14/0110/17/15459414_344165975.shtml 如今利用nginx做负载均衡的实例已经很多了,针对不同的应用场 ...