windows c++ (5) 获取系统服务名称和状态

最近项目比较多,现在终于算是告一段落。现在整理一下目前用到的一些功能和一些注意点。
本次说的是c++获取系统的服务名称和状态(主要用于监控项目发布的服务状态,配合监控界面和后台守护服务确保服务正常运行)。

1、代码实现

#include  <map>
#include <Windows.h>   //此头文件不建议放在.h类的文件里#define SERVICE_STA_UN 111typedef struct						
{string	strName;//服务名称int		nSta;	//服务状态
}AllSerInfo; //服务结构体map<string,AllSerInfo> g_allService; void GetServices() {	g_allService.clear();do{AllSerInfo temp_stu;//1 打开服务管理SC_HANDLE schandle = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (schandle == NULL){cout << "打开服务管理失败" << endl;break; //跳出}//2 初始化申请内存LPENUM_SERVICE_STATUS service_staus; //系统服务的结构   DWORD cbBytesNeeded = 0;DWORD serviceReturned = 0;DWORD resumeHandle = 0;DWORD len = sizeof(ENUM_SERVICE_STATUSW);service_staus = (LPENUM_SERVICE_STATUS)LocalAlloc(LPTR, MAX_SERVICE_SIZE);if (service_staus == nullptr){cout << "申请内存失败" << endl;break;}//3 枚举服务内容BOOL ess = ::EnumServicesStatus(schandle, //句柄SERVICE_WIN32, //服务类型 SERVICE_DRIVER驱动 SERVICE_TYPE_ALL所有SERVICE_STATE_ALL, //服务的状态service_staus, //输出参数,系统服务的结构MAX_SERVICE_SIZE, //结构的大小&cbBytesNeeded, //输出参数,接收返回所需的服务&serviceReturned, //输出参数,接收返回服务的数量&resumeHandle); //输入输出参数,第一次调用必须为0,返回0代表成功if (!ess){cout << "枚举失败" << endl;break;}//4 解析赋值服务名称和状态for (int i = 0; i < serviceReturned; i++){ENUM_SERVICE_STATUS service = service_staus[i];string displayName = service.lpDisplayName;string serviceName = service.lpServiceName;temp_stu.strName = serviceName;switch (service.ServiceStatus.dwCurrentState) //服务状态{case       SERVICE_STOPPED:temp_stu.nSta = SERVICE_STOPPED; //服务未运行。break;case       SERVICE_START_PENDING:temp_stu.nSta = SERVICE_START_PENDING; //服务正在启动。break;case       SERVICE_STOP_PENDING:temp_stu.nSta = SERVICE_STOP_PENDING; // 服务正在停止。break;case       SERVICE_RUNNING:temp_stu.nSta = SERVICE_RUNNING; //服务正在运行。break;case      SERVICE_CONTINUE_PENDING:temp_stu.nSta = SERVICE_CONTINUE_PENDING; // 服务即将继续。break;case     SERVICE_PAUSE_PENDING:temp_stu.nSta = SERVICE_PAUSE_PENDING; // 服务即将暂停。break;case     SERVICE_PAUSED:temp_stu.nSta = SERVICE_PAUSED; // 服务已暂停。break;default:cout << "未知状态" << endl;temp_stu.nSta = SERVICE_STA_UN ;  break;}//5 如果需要对比服务路径是否正确可以用下面的 否则可以不调用LPQUERY_SERVICE_CONFIG lpServiceConfig = nullptr; //服务详细信息结构SC_HANDLE service_current = nullptr; //当前的服务句柄service_current = ::OpenService(schandle, service.lpServiceName, SERVICE_QUERY_CONFIG); //打开当前服务if (service_current == nullptr){cout << "当前服务打开失败" << endl;break;}lpServiceConfig = (LPQUERY_SERVICE_CONFIG)::LocalAlloc(LPTR, MAX_QUERY_SIZE); //分配内存,最大为8KBif (lpServiceConfig == nullptr){cout << "申请LPQUERY_SERVICE_CONFIG内存失败" << endl;break;}if (!::QueryServiceConfig(service_current, lpServiceConfig, MAX_QUERY_SIZE, &resumeHandle)){cout << "查询服务失败" << endl;break;}cout << "服务显示名称:" << displayName << " 服务名称:" << serviceName  << "路径:" << lpServiceConfig->lpBinaryPathName << endl;g_allService[serviceName] = temp_stu;LocalFree(lpServiceConfig);::CloseServiceHandle(service_current);// 关闭当前服务}LocalFree(service_staus);::CloseServiceHandle(schandle); //关闭服务} while (0);
}

2、方法解析

2.1 OpenSCManager

与指定计算机上的服务控制管理器建立连接,并打开指定的服务控制管理器数据库。

SC_HANDLE OpenSCManagerA([in, optional] LPCSTR lpMachineName,[in, optional] LPCSTR lpDatabaseName,[in]           DWORD  dwDesiredAccess
);
参数解析
lpMachineName目标计算机的名称。 如果指针为 NULL 或指向空字符串,则函数将连接到本地计算机上的服务控制管理器。
lpDatabaseName服务控制管理器数据库的名称。 此参数应设置为 SERVICES_ACTIVE_DATABASE。 如果为 NULL,则默认打开SERVICES_ACTIVE_DATABASE数据库。
dwDesiredAccess对服务控制管理器的访问。 有关访问权限的列表,请参阅 服务安全性和访问权限。

dwDesiredAccess 传参

//
// Service Control Manager object specific access types
//
#define SC_MANAGER_CONNECT             0x0001 //允许连接服务控制管理器。
#define SC_MANAGER_CREATE_SERVICE      0x0002 //表示拥有注册(创建)服务的权限。
#define SC_MANAGER_ENUMERATE_SERVICE   0x0004 //表示拥有枚举系统服务的权限
#define SC_MANAGER_LOCK                0x0008 // 允许锁定服务数据库。
#define SC_MANAGER_QUERY_LOCK_STATUS   0x0010 //允许查询服务数据库的锁定状态。
#define SC_MANAGER_MODIFY_BOOT_CONFIG  0x0020 //允许修改系统启动配置。//SC_MANAGER_ALL_ACCESS 表示拥有一切权限
#define SC_MANAGER_ALL_ACCESS          (STANDARD_RIGHTS_REQUIRED      | \SC_MANAGER_CONNECT            | \SC_MANAGER_CREATE_SERVICE     | \SC_MANAGER_ENUMERATE_SERVICE  | \SC_MANAGER_LOCK               | \SC_MANAGER_QUERY_LOCK_STATUS  | \SC_MANAGER_MODIFY_BOOT_CONFIG)

2.2 LocalAlloc

从堆中分配指定的字节数。

注意 与其他内存管理功能相比,本地函数的开销更大,提供的功能更少。 除非文档指出应使用本地函数,否则新应用程序应使用 堆 函数。 有关详细信息,请参阅 全局和本地函数。
语法:

DECLSPEC_ALLOCATOR HLOCAL LocalAlloc([in] UINT   uFlags,[in] SIZE_T uBytes
);

Windows 内存管理不提供单独的本地堆和全局堆。 因此, LocalAllo 和 GlobalAlloc 函数实质上是相同的。(有机会可以看看,还有对应的lock锁的应用)

可移动内存标志 LHND、 LMEM_MOVABLE 和 NONZEROLHND 会增加不必要的开销,并要求安全使用锁定。 除非文档明确指出应使用它们,否则应避免使用它们。

除非文档特别指出应使用本地函数,否则新应用程序应使用 堆 函数。 例如,某些 Windows 函数分配必须使用 LocalFree 释放的内存。

如果堆不包含满足请求的足够可用空间, 则 LocalAlloc 返回 NULL。 由于 NULL 用于指示错误,因此永远不会分配虚拟地址 0。 因此,很容易检测到 NULL 指针的使用。

如果 LocalAlloc 函数成功,它将至少分配请求的量。 如果分配的金额大于请求的金额,则进程可以使用整个金额。 若要确定实际分配的字节数,请使用 LocalSize 函数。

若要释放内存,请使用 LocalFree 函数。 使用 GlobalFree 释放通过 LocalAlloc 分配的内存是不安全的。

在上面的例子,原先我是直接网上copy 的,里面没有调用LocalAlloc 释放。大家拷贝注意验证
示例:(LocalAlloc类似 将Global换成Local)

// Malloc memory
hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, nSize);
// Lock memory
pMem = (BYTE *) GlobalLock(hMem);
..................
// Unlock memory
GlobalUnlock(hMem);
GlobalFree(hMem);

3 后记

在网上看到个设置SCM服务加解析的,解释很详细感觉不错贴过来备忘
注册服务:

#include <stdio.h>
#include <windows.h>
#include <Shlwapi.h>
#include<strsafe.h>
#pragma comment(lib,"Shlwapi")//注册服务自启动
void AutoRunService(char* szFilePath, char* lpDisplayName)
{char szServiceName[MAX_PATH] = { 0 };//服务名称SC_HANDLE hSCM;//服务控制管理器,根据服务控制管理器,可以对服务进行查询、创建、启动、停止操作。SC_HANDLE hService; //本次要注册的服务句柄//查到服务控制管理器的句柄hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);//从.sys文件中拿到服务名,服务名即等价于文件名::StringCchCopy(szServiceName,_countof(szServiceName), szFilePath);::PathStripPath(szServiceName);//查一下要注册的服务已经被服务控制管理器管理了没有hService = ::OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);if (hService == NULL) {//没有则创建出此服务,并让此服务开机自启动 然后启动服务。SC_HANDLE hNewService = ::CreateService(hSCM, szServiceName, lpDisplayName, SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,SERVICE_ERROR_IGNORE, szFilePath,NULL, NULL, NULL, NULL, NULL);::StartService(hNewService, 0, NULL);::CloseServiceHandle(hNewService);printf("[*] 创建服务完成 \n");}::CloseServiceHandle(hService);::CloseServiceHandle(hSCM);}// 设置服务状态
BOOL SetServiceStatus(char* lpServiceName, int Status)
{SERVICE_STATUS ss;SC_HANDLE hSCM;//服务控制管理器,根据服务控制管理器,可以对服务进行查询、创建、启动、停止操作。BOOL bRet = TRUE;SC_HANDLE hService;//要设置服务状态的服务//查到服务控制管理器的句柄hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);//从服务控制管理器中 依据服务名称 查到此设置服务状态的服务,hService = ::OpenService(hSCM, lpServiceName, SERVICE_ALL_ACCESS);if (hService != NULL){if (Status == 1) //用户要求停止服务{if (!::ControlService(hService, SERVICE_CONTROL_STOP, &ss)){bRet = FALSE;}}else if (Status == 2) //用户要求启动服务{if (!::StartService(hService, 0, NULL)){bRet = FALSE;}}else if (Status == 3) //用户要求删除服务{if (!DeleteService(hService)){bRet = FALSE;}}else{//todo...}}CloseServiceHandle(hSCM);CloseServiceHandle(hService);return bRet;}
int main(int argc, char* argv[])
{// 注册为自启动服务将d:/myservice.exe 注册为自启动服务 后面是描述信息AutoRunService((char*)"d:/myservice.exe", (char*)"Microsoft Windows Security Services");// 根据服务名称管理服务 1=>停止服务 2=>启动服务 3=>删除服务BOOL ret = SetServiceStatus((char*)"myservice.exe", 2);printf("状态: %d \n", ret);return 0;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/583423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件下载输出zip文件

文件下载输出成zip文件&#xff1a; 1、前端整个按钮&#xff0c;调js方法&#xff1a;&#xff08;参数&#xff1a;param,需要下载的id&#xff0c;用逗号拼接&#xff09; var param "?dto.id";//需要自己拼接param window.location.href "<%basePat…

城市分站优化系统源码:提升百度关键排名 附带完整的搭建教程

城市分站优化已成为企业网络营销的重要手段&#xff0c;今天来给大家分享一款城市分站优化系统源码。 以下是部分代码示例&#xff1a; 系统特色功能一览&#xff1a; 1.多城市分站管理&#xff1a;该系统支持多个城市分站的管理&#xff0c;用户可以根据业务需求&#xff0c;…

官网万词霸屏推广源码系统:轻松实现百度上万关键词排名在线

互联网的快速发展&#xff0c;网络营销已经成为企业推广的重要手段。在这个竞争激烈的市场中&#xff0c;如何让自己的网站在搜索引擎中获得更好的排名&#xff0c;成为众多企业关注的焦点。而万词霸屏推广源码系统正是在这样的背景下应运而生&#xff0c;为企业提供了一种全新…

【深入浅出Java性能调优】「底层技术原理体系」深入探索Java服务器性能监控Metrics框架的实现原理分析(Gauge和Histogram篇)

承接上文 承接上文中的【深度挖掘Java性能调优】「底层技术原理体系」深入探索Java服务器性能监控Metrics框架的实现原理分析&#xff08;Counter篇)&#xff0c;我们知道和了解了对应的Counter计数器的作用和实现原理&#xff0c;接下来我们需要进行分析和了解计量器&#xf…

【DB2】Maxlocks和防止锁升级

数据库在对行操作的时候&#xff0c;为了避免多个作业互相覆盖影响数据准确性&#xff0c;在进行操作&#xff08;尤其是写操作&#xff09;的时候会上锁&#xff0c;同一时间只有一个作业可以修改数值 对行上锁&#xff0c;为了记录锁的信息&#xff0c;所以会占用一定的内存…

面试题:MySQL 自增主键一定是连续的吗?

文章目录 测试环境&#xff1a;一、自增值的属性特征&#xff1a;1. 自增主键值是存储在哪的&#xff1f;2. 自增主键值的修改机制&#xff1f; 二、新增语句自增主键是如何变化的&#xff1a;三、自增主键值不连续情况&#xff1a;&#xff08;唯一主键冲突&#xff09;四、自…

uniapp:全局消息是推送,实现app在线更新,WebSocket,apk上传

全局消息是推送&#xff0c;实现app在线更新&#xff0c;WebSocket 1.在main.js中定义全局的WebSocket2.java后端建立和发送WebSocket3.通知所有用户更新 背景&#xff1a; 开发人员开发后app后打包成.apk文件&#xff0c;上传后通知厂区在线用户更新app。 那么没在线的怎么办&…

零碳、碳达峰、碳中和的概念和区别

零碳 “零碳”是一个旨在减少碳排放、减缓气候变化的全球性概念。它并不是指完全不排放二氧化碳&#xff0c;而是通过计算温室气体&#xff08;主要是二氧化碳&#xff09;排放&#xff0c;设计方案抵减“碳足迹”、减少碳排放&#xff0c;达到碳的零排放。这需要人们在社会生…

使用electron属性实现保存图片并获取图片的磁盘路径

在普通的网页开发中&#xff0c;JavaScript由于安全性的考虑&#xff0c;通常是无法直接获取到客户端的磁盘路径的。浏览器出于隐私和安全原因对此类信息进行了限制。 在浏览器环境下&#xff0c;JavaScript主要通过Web APIs来与浏览器进行交互&#xff0c;而这些API通常受到浏…

【C++】内存泄漏排查

前言 内存泄漏影响程序的稳定性运行&#xff0c;并且在程序运行过程中&#xff0c;并不会报错误&#xff0c;需要借助专用的内存泄露工具进行检测。 工具&#xff1a;CLion and AddressSanitizer #include <iostream> using namespace std;int main() {char *c new ch…

【北亚服务器数据恢复】ZFS文件系统服务器ZPOOL下线的数据恢复案例

服务器数据恢复环境&#xff1a; 服务器中有32块硬盘&#xff0c;组建了3组RAIDZ&#xff0c;部分磁盘作为热备盘。zfs文件系统。 服务器故障&#xff1a; 服务器运行中突然崩溃&#xff0c;排除断电、进水、异常操作等外部因素。工作人员将服务器重启后发现无法进入操作系统。…

Python异常总结

一 异常 当Python检测到一个错误时&#xff0c;解释器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的"异常"。 print -----test--1--- open(123.txt,r) # 此处发生异常&#xff0c;程序崩溃 print -----test--2---异常需要…

IPD-PDP产品开发流程-PDT产品开发计划Charter文档模板(word)2

书接上回&#xff0c;继续为大家分享PDT的产品开发计划Charter模板的主要内容。 据华研荟了解&#xff0c;大部分国内的企业在推行IPD的时候就直接像华为一样&#xff0c;把开发计划&#xff08;任务书&#xff09;叫做Charter&#xff0c;而不翻译为中文。其实这也是一种很好…

Roary结果中有基因组丢失怎么办

Roary结果里面有基因组没在结果里出现&#xff1f;&#xff1f;&#xff01; 看看是不是结果文件夹里有一个文件夹叫fixed_input_files 如果有&#xff0c;你可以检查一下自己提交的gff文件里是不是每个不同的ORF&#xff08;可以理解为基因&#xff09;都在最后一列ID有自己独…

超图iClient3DforCesium地形、影像、模型、在线影像交互示例

超图iClient3DforCesium地形、影像、模型、在线影像交互示例 描述示例代码 描述 数据源&#xff1a;基于iserver发布的三维场景(地形、影像、BIM模型) 在线arcgis影像 应用&#xff1a;目录树展示源数据列表、目录树控制源数据可视化结果显隐、BIM模型点选查询关联属性 示例代…

水果软件2024FL Studio21.3mac苹果中文版

FL STUDIO21发布&#xff0c;提供您一直在等待的出色工作流程功能。通过新效果、多个播放列表曲目选择和无所畏惧的撤消一切编辑&#xff0c;将您的音乐带入2024年。FL Studio21中文完整版是一个功能齐全、开放式架构的PC音乐创作和制作环境。它具有基于音乐音序器的图形用户界…

详细讲解node的ws中服务端的websocket.server的各种api

WebSocket是一种在单个TCP连接上进行全双工通信的协议。Node.js中的ws模块提供了WebSocket的实现&#xff0c;使得Node.js可以轻松地创建WebSocket服务器和客户端。 在ws模块中&#xff0c;WebSocket服务器由WebSocket.Server类实现。WebSocket.Server提供了一系列的API&#…

Anolis8/centos8/龙蜥8 升级glibc 2.30

背景&#xff1a; Anolis8/centos8/龙蜥8 系统自带的glibc是2.28版本&#xff0c;已经无法满足项目需要&#xff0c;所以将glibc版本升级到2.30。 编译升级安装 wget https://mirrors.aliyun.com/gnu/glibc/glibc-2.30.tar.gz tar -xvf glibc-2.30.tar.gz #查看glibc需要的g…

STL——list容器

目录 1.list基本概念 2.list构造函数 3.list赋值和交换 4.list大小操作 5.list插入和删除 6.list数据存取 7.list反转和排序 8.排序案例 1.list基本概念 功能&#xff1a;将数据进行链式存储。 链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结构&…

SpringBoot-Shiro

Apache Shiro&#xff1a;https://shiro.apache.org/ 依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.1</version> </dependency>ShiroConfig.java Configuratio…