用VC++开发Windows服务

C++编写服务程序 近段时间,在学习使用C++写windows服务。参考了若干的资料,写如下服务,作为学习笔记。 写服务主要有一下步骤 1、使用 StartServiceCtrlDispatcher(SERVICE_TABLE_ENTRY lpServiceStartTable);连接SCM,让SCM控制函数。需要注意的是最后lpServiceStartTable的最后一个结构体的两个属性值都是NULL 2、编 阅读详情
用.net开发服务很简单,此处讲解使用VC++开发Windows服务
1. 服务的组成
一个服务由三部分组成:
第一部分Service Control Manager(SCM),每个Windows系统都有一个SCM,SCM存在于Service.exe中,在Windows启动的时候会自动运行,伴随着操作系统的启动和关闭而产生和终止;
第二部分为服务本身,一个服务拥有能从SCM收到信号和命令所必须的特殊代码,并且能在处理后将它的状态回传回SCM;
第三部分是Service Control Dispatcher(SCP),是一个拥有用户界面,允许用户开始、停止、暂停、继续,并且控制一个或多个安装在计算机上服务的Win32应用程序。

2. 三个重要函数
2.1 服务程序入口函数
头文件:Winsvc.h 
库:Advapi32.lib
DLL:Advapi32.dll

BOOL WINAPI StartServiceCtrlDispatcher(
  _In_  const SERVICE_TABLE_ENTRY *lpServiceTable
);

2.2 服务入口回调函数
头文件:Winsvc.h
VOID WINAPI ServiceMain(
  _In_  DWORD dwArgc,
  _In_  LPTSTR *lpszArgv
);

2.3 服务控制回调函数
VOID WINAPI CtrlHandler(DWORD fdwControl) //控制命令

下面是一个摘录于<计算机病毒揭秘与对抗>>作者:王倍昌一书中的例子,可以编译到控制台下直接使用,可以看做是编写服务的一个框架。
服务的功能是监控系统中的可移动磁盘,然后向其中写入文件a.txt。

编译后执行 FirstService.exe install 安装服务,然后在服务窗口中启动该服务。
卸载服务  FirstService.exe uninstall

// FirstService.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <tchar.h>
#define SERVICE_NAME _T("FirstService")
SERVICE_STATUS g_status;
SERVICE_STATUS_HANDLE g_hServiceStatus;
HANDLE g_hEvent = NULL;
void Init()
{
g_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_status.dwCurrentState = SERVICE_STOPPED;
// 设置服务可以使用的控制
// 如果希望服务启动后不能停止,去掉SERVICE_ACCEPT_STOP
// SERVICE_ACCEPT_PAUSE_CONTINUE是服务可以“暂停/继续”
g_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
g_status.dwWin32ExitCode = 0;
g_status.dwServiceSpecificExitCode = 0;
g_status.dwCheckPoint = 0;
g_status.dwWaitHint = 0;
//创建初始为有信号的手动内核事件。
g_hEvent = CreateEvent(NULL, TRUE, TRUE, "Pause");
}


void SetStatus(long lCurrentStatus)
{
g_status.dwCurrentState = lCurrentStatus;
SetServiceStatus(g_hServiceStatus, &g_status);
}


void WINAPI Handler(DWORD dwOpcode)
{
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
{ //收到停止服务命令停止服务
SetStatus(SERVICE_STOP_PENDING);
SetStatus(SERVICE_STOPPED);
}
break;
case SERVICE_CONTROL_PAUSE:
{
SetStatus(SERVICE_PAUSE_PENDING);
ResetEvent(g_hEvent); //通知RUN函数开始等待
SetStatus(SERVICE_PAUSED);
}
break;
case SERVICE_CONTROL_CONTINUE:
{
SetStatus(SERVICE_CONTINUE_PENDING);
SetEvent(g_hEvent);//通知RUN函数继续执行
SetStatus(SERVICE_RUNNING);
}
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
{ //关机时停止服务
SetStatus(SERVICE_STOP_PENDING);
SetStatus(SERVICE_STOPPED);
}
break;
default:
break;
}
}


void Run()
{
while (1)   //循环扫描系统磁盘
{
TCHAR tcBuffer[4] = {0}; //准备较小内存,先试探出实际需要的内存大小。
DWORD dwNeededSize = GetLogicalDriveStrings(4, tcBuffer); //第一次执行,获得实际需要内存。
if (dwNeededSize > 4)
{   //返回值大于指定内存大小,需要重新准备足够内存再次执行。
TCHAR *pBuffer = new TCHAR[dwNeededSize];  //准备足够大的内存
dwNeededSize = GetLogicalDriveStrings(dwNeededSize, pBuffer); //获得逻辑驱动器字符串
TCHAR *pDrive = pBuffer;
int iPreLength = 0;
while (1)
{
pDrive = pBuffer+iPreLength;  //获得下一个驱动器
if (pDrive[0] == 0) //获取驱动器结束
{
break; //退出循环
}
DWORD dwDriveType = GetDriveType(pDrive); //获取驱动器类型
if (dwDriveType == DRIVE_REMOVABLE)
{   //如果是移动驱动器
TCHAR tcFile[MAX_PATH] = {0};
_stprintf(tcFile, _T("%sa.txt"), pDrive);
//打开已存在的a.txt文件
HANDLE hFile = CreateFile(tcFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
//打开失败则创建一个。
hFile = CreateFile(tcFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWrite = 0;
WriteFile(hFile, _T("Hello"), 5, &dwWrite, NULL);
}
CloseHandle(hFile);
}
iPreLength += _tcslen(pDrive);  //跳过当前驱动器
iPreLength += 1;//sizeof(TCHAR);    //跳过'\0'。 应该是字符数,加1跳过\0才对
}
if (pBuffer != NULL)
{
delete []pBuffer;  //释放内存
pBuffer = NULL;
}
}
Sleep(500);  //暂停500毫秒后继续扫描
//如何g_hEvent无信号则暂停执行
WaitForSingleObject(g_hEvent, INFINITE);
}
}


void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
// 注册控制请求句柄
g_hServiceStatus = RegisterServiceCtrlHandler(SERVICE_NAME, Handler);
if (g_hServiceStatus == NULL) return;
SetStatus(SERVICE_START_PENDING);
SetStatus(SERVICE_RUNNING);
// 当 Run 函数返回时,服务已经结束。
Run();
g_status.dwWin32ExitCode = S_OK;
g_status.dwCheckPoint = 0;
g_status.dwWaitHint = 0;
g_status.dwCurrentState = SERVICE_STOPPED;
//设置服务状态为停止,从而退出服务.
SetServiceStatus(g_hServiceStatus, &g_status);
}


BOOL IsInstalled()
{
    BOOL bResult = FALSE;
//打开服务控制管理器
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);


    if (hSCM != NULL)
    {
//打开服务
        SC_HANDLE hService = OpenService(hSCM, SERVICE_NAME, SERVICE_QUERY_CONFIG);
        if (hService != NULL)
        {
            bResult = TRUE;
            CloseServiceHandle(hService);
        }
        CloseServiceHandle(hSCM);
    }
    return bResult;
}


BOOL Install()
{
    if (IsInstalled()) //服务已安装则直接返回真
        return TRUE;


//打开服务控制管理器
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hSCM == NULL)
    {
        return FALSE;
    }


    TCHAR szFilePath[MAX_PATH];
   DWORD dwLen = GetModuleFileName(NULL, szFilePath, MAX_PATH);
   //判断程序路径是否包含空格,如果包含则给路径加上引号.
   if (_tcschr(szFilePath, ' ') != NULL)
   {
  dwLen += 3;
  TCHAR *lpFilePath = new TCHAR[dwLen];
  if (lpFilePath != NULL)
  {
  _stprintf(lpFilePath, _T("\"%s\""), szFilePath);
  _tcscpy(szFilePath, lpFilePath);
  delete []lpFilePath;
  }
}
//创建一个手动启动的服务
    SC_HANDLE hService = CreateService(
        hSCM, SERVICE_NAME, SERVICE_NAME,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL, _T(""), NULL, NULL);


    if (hService == NULL)
    {
        CloseServiceHandle(hSCM);
        return FALSE;
    }
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCM);
    return TRUE;
}


BOOL Uninstall()
{
    if (!IsInstalled()) //如果服务已卸载直接返回真
        return TRUE;
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);


    if (hSCM == NULL)
    {
        return FALSE;
    }
    SC_HANDLE hService = OpenService(hSCM, SERVICE_NAME, SERVICE_STOP | DELETE);
    if (hService == NULL)
    {
        CloseServiceHandle(hSCM);
        return FALSE;
    }
    SERVICE_STATUS status; 
//首先停止服务,确保服务能够立即被删除.
    ControlService(hService, SERVICE_CONTROL_STOP, &status);
//删除服务
    BOOL bDelete = DeleteService(hService);
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCM);
    if (bDelete)
        return TRUE;
    return FALSE;
}


int main(int argc, char* argv[])
{
Init(); //初始化服务数据信息
//判断参数决定如何执行代码
if (argv[1] != NULL && _tcsicmp(argv[1], _T("install")) == 0)
{
Install();
}
else if (argv[1] != NULL && _tcsicmp(argv[1], _T("uninstall")) == 0)
{
Uninstall();
}
else
{ //如果没有参数则是由SCM启动的服务程序
SERVICE_TABLE_ENTRY st[] =
{
{ SERVICE_NAME, ServiceMain },
{ NULL, NULL }
};
StartServiceCtrlDispatcher(st);
}
CloseHandle(g_hEvent);
return 0;
}









告别卡顿与兼容烦恼:Dependencies,现代Windows VC++开发的依赖分析利器 本文介绍了Dependencies工具在现代Windows VC++开发中的重要作用,帮助开发者解决DLL依赖、兼容性和卡顿问题。通过详细的功能解析和实战案例,展示了如何利用Dependencies快速定位和修复依赖问题,提升开发效率。工具完全兼容Win10/11系统,支持64位程序分析,是替代传统Depends的理想选择。 阅读详情

相关推荐

使用C++编写Windows系统服务

在Windows操作系统中,系统服务是一种在后台运行的应用程序,它可以在系统启动时自动加载并在后台执行特定的任务。服务通常用于处理系统级别的功能,如网络通信、文件管理和系统监控等。本文将介绍如何使用C++编写Windows系统服务,并提供相应的源代码示例。

DevScript的博客 769

VC++创建windows服务程序

VC++创建windows服务程序

hsy12342611的专栏 4741

用 VC++建立 Windows 服务程序

1.最简单的创建一个windows service程序 (1)新建一个win32控制台程序 (2)开始-&gt;运行-&gt;cmd,必须右键—&gt;以管理员身份运行,此时进入dos命令提示符界面。 (3)输入 sc create test binPath= “D:\Code_Test\VS2012_test\test_console\test_console\Release\test_cons...

技术联盟 2073

C++编写Windows服务

原文地址:点击打开链接服务是一个运行在后台并且无需用户交互的控制台程序。可以通过在“开始-&gt;运行”中输入services.msc,打开系统的服务并进行配置。服务的实现与安装:第一步:    主函数和全局定义 首先,包含所需的头文件:#include &lt;Windows.h&gt; //调用 Win32 函数 #include &lt;stdio.h&gt;//磁盘文件写入然后,定义两个常...

mpp_king的博客 6847

VC++6.0 MSDN3中文版完整开发者资源包

VC++6.0作为微软推出的经典C++集成开发环境,曾是许多程序员的首选工具。它将源代码编辑器、编译器、调试器和各种工具集于一体,使得开发者可以在一个统一的平台上完成从编码到调试的全过程。尽管该产品推出已有多年,但在一些特定的行业和项目中,它仍不失为一个稳定而高效的开发选择。

weixin_29997223的博客 786

Windows服务开发实战:源码详解

Windows服务是一种特殊的Windows程序,它能够在没有任何用户登录的情况下运行。服务通常负责提供系统级别的功能,如网络通信、设备驱动、文件和打印服务等。服务可以启动、停止、暂停、恢复,以及在系统启动时自动运行。创建一个自定义服务控制程序不仅需要熟练使用Win32 API,还需要了解服务的内部工作原理。以下是一个简单的自定义服务控制程序的示例,展示了如何结合前面提到的控制代码。break;break;break;return 0;

weixin_32999557的博客 791

VC++6开发Windows服务程序

下面介绍使用VC++开发Windows服务程序。         首先运行VC++6,选择新建工程,在出现的下面窗口中选择”ATL COM AppWizard“,并选择工程放置位置和相应的工程名,然后选择确定按钮。 此时出现如下图窗口界面,在此界面中选择”服务(EXE)“,然后选择完成按钮。 在接下来的窗口中选择确定按钮。 则VC完成向导并生成相应代码(效果如下)。

lhsxsh的专栏 8503

光纤布拉格光栅(FBG)笔记【1】:波导结构和布拉格波长推导

引言 本文是光纤布拉格光栅(FBG)的笔记【1】,主要介绍了光纤布拉格光栅的波导结构,并且利用动量和能量守恒推导了光纤布拉格波长的表达式 普通光纤中让折射率发生周期性变化就是结构最简单的均匀光纤布拉格光栅(FBG),其波导结构如下图所示。 其传感原理描述可以分为以下的三点: ①光纤纤芯传播的光会在每个光栅面进行反射和透射; ②如果不满足布拉格条件,依次排列的光栅平面反射的光会逐渐变得不同直到最后相互抵消;同时由于系数不匹配,与布拉格波长不相符的光在每个光栅平面的反射也很微弱,这些光大部分在光纤中发生透.

subtitle_的博客 2万+

VC++6开发Windows服务程序 .

转至: http://blog.youkuaiyun.com/lhsxsh/article/details/7108802      下面介绍使用VC++开发Windows服务程序。         首先运行VC++6,选择新建工程,在出现的下面窗口中选择”ATL COM AppWizard“,并选择工程放置位置和相应的工程名,然后选择确定按钮。 此时出现如下图窗口界面,在此界面中选择”服务(EX

闲云野鹤 的专栏 2822

SAP高级外币评估_FINS_FXV_S4 2022 OP

摘要:S/4HANA 2022 On-Premise中的高级外币评估(FINS_FXV)取代了经典外币估值(FAGL_FCV),提供更优化的财务结算功能。主要创新包括:增量发布逻辑、简化账户配置、行项目级估值可见性等。该功能支持IFRS9等会计准则,通过会计原则(Accounting Principle)进行配置,需完成财务报表版本定义、语义标记分配等必要设置。系统演示展示了从汇率维护(FB60/MIRO)、测试运行到最终过账(FB03)的完整流程,能自动计算并过账汇率差异。高级外币评估简化了期末结算操作,

yanzibing99的博客 1260

SeetaFace6人脸活体检测C++代码实现Demo

活体检测是判断人脸图像是来自真人还是来自攻击假体(照片、视频等)的方法。 人脸识别系统存在被伪造攻击的风险。因此需要在人脸识别系统中加入活体检测,验证用户是否为真实活体本人操作,以防止照片、视频、以及三维模型的入侵,从而帮助用户甄别欺诈行为,保障用户的利益。

mickey2007的博客 3477

VC++6.0开发Windows服务程序。

        首先运行VC++6,选择新建工程,在出现的下面窗口中选择”ATL COM AppWizard“,并选择工程放置位置和相应的工程名,然后选择确定按钮。此时出现如下图窗口界面,在此界面中选择”服务(EXE)“,然后选择完成按钮。在接下来的窗口中选择确定按钮。则VC完成向导并生成相应代码(效果如下)。        程序的进入点是全局函数_tWinMain, 仔细看一下这个函数,我们会发

思源领航 4842

基于FISCO BCOS 部署可升级的 Solidity存证智能合约

本文介绍了基于FISCOBCOS平台的可升级Solidity存证智能合约实现方案。采用透明代理模式,包含逻辑合约、代理合约和管理合约三部分,支持业务逻辑升级而不影响存储数据。详细阐述了合约架构设计、Solidity代码实现、Go SDK交互流程以及完整的部署升级步骤。方案具有数据持久性、版本兼容性和生产就绪等特点,提供了权限控制、输入验证等安全机制,并包含监控管理工具。该实现为企业级区块链存证应用提供了可靠的基础架构,支持后续功能扩展和定制化开发。

分享AI、区块链技术及应用,未来已来 1515

vs vc++ 开发 windows 服务的参考文章及代码网址

vs 开发 windows 服务的参考文章及代码网址

zhangxiaonanwin的专栏 732

YOLOv8多传感器融合技术——摄像头阵列融合技术详解

本文详细介绍了基于YOLOv8的摄像头阵列融合技术,该技术通过多摄像头协同工作实现360度无死角环境感知。文章阐述了系统原理,包括全方位视野覆盖、冗余设计和深度感知等优势,并提供了完整的Python实现代码。关键技术涵盖多摄像头检测、立体匹配、3D投影和目标融合等模块,支持时间域融合提升稳定性。该系统可显著提高自动驾驶的环境感知能力,减少检测盲区,增强系统可靠性,是L4-L5级自动驾驶的关键技术之一。文章还展示了城市驾驶场景的实际应用,验证了该技术对复杂交通环境的适应能力。

u010117029的博客 213

EMC基础知识总结

电磁干扰(Electromagnetic Interference),简称EMI,有和两种。传导干扰主要是电子设备产生的干扰信号通过导电介质或公共电源线互相产生干扰;辐射干扰是指电子设备产生的干扰信号通过空间耦合把干扰信号传给另一个电网络或电子设备。

学海无涯的专栏 1370

VC++ 给Windows服务添加描述信息

#include &lt;windows.h&gt; /** * 更新(添加)服务描述。 * @param serviceName : 服务名称。 * @param serviceDescription : 服务描述。 */ bool updateServiceDescription(const char *serviceName, LPTSTR serviceDescription)...

WSG的博客--盛年不重来,一日难再晨.及时当勉励,岁月不待人. 1151

本地构建AI智能分析助手之 05 PandasAI如何MySQL数据库 (教程含源码)

与 PostgreSQL 连接器类似,MySQL 连接器允许您连接到 MySQL 数据库。即使您不熟悉 MySQL 或 PandasAI,它也设计得易于使用。

iCloudEnd的博客 704

用 VC++ 和 Winsock 实现与 HTTP 服务器通话

用 VC++ 和 Winsock 实现与 HTTP 服务器通话 作者:Ji Hong 一、引 言 ---- Windows Socket API是一套开放的、支持多种协议的Windows下的网络编程接口,它包 括一个标准的 Berkeley Socket功能调用的集合,以及为Windows所作的重要扩充。 Windows Socket经过不断完善并在众 多公司的全力

ren20的专栏 1139

详解大端模式和小端模式

详解大端模式和小端模式 一、大端模式和小端模式的起源         关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令

ce123的技术博客 19万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

基于VC++的Modbus TCP协议实现

基于VC++的Modbus TCP协议实现 去发现同类优质开源项目:https://gitcode.com/ 简介 本仓库提供了Modbus TCP协议在VC++环境下的实现代码。Modbus协议是一种串行通信协议,广泛应用于工业领域,主要用于工业设备之间的通信。本资源文件旨在帮助开发者理解和运用VC++进行Modbus TCP协议的开发。 功能 实现Modbus TCP协议的客户端与服务器端通...

gitblog_06704的博客 489

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

《VC++修改系统服务的启动类型并启动服务》的详细实现,基于Windows平台的VC++环境,使用Windows API(如OpenSCManager、OpenService

以下是关于《VC++修改系统服务的启动类型并启动服务(附源码)》的详细实现,基于Windows平台的VC++环境,使用Windows API(如OpenSCManager、OpenService、ChangeServiceConfig和StartService)来修改系统服务的启动类型并启动服务。扩展功能如停止服务、状态查询进一步增强实用性。支持设置服务的启动类型:自动(SERVICE_AUTO_START)、手动(SERVICE_DEMAND_START)、禁用(SERVICE_DISABLED)。

专注于前沿技术的探索与实践,热衷于从代码逻辑、架构设计到行业应用等多维度深挖技术本质。期待在技术之路上与你共同成长~ 678

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

在VC++中利用ActiveX控件开发串行通信程序

在开发微机控制系统的过程中,我们经常需要通过RS-232串行接口与外部设备进行通信。例如分级控制系统中上位机与下位机的数据交换以及数据采集系统中计算机与数字仪表的通信等。在DOS时代,编写串行通信程序是一件相当复杂的工作,程序员需要具备相当的硬件知识,对可编程串行通信接口芯片的内部寄存器定义、工作方式、指令字等相关内容有所了解,才有可能着手编写程序,大量的时间和精力都花在了如何与硬件打交道上,而...

javasogo 152
上一篇: Windows时间CTime与SYSTEMETIME格式化
下一篇: 关于WinCE调用RegDeleteKey不能删除注册表项的问题
ComputerInBook
博客等级 码龄19年 1168粉丝 464原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值