windows创建服务:更新服务信息乱码问题(ChangeServiceConfig)
因为小项目需要创建windows服务,安装微软官方示例一切都挺顺利,代码运行后发现配置的信息在系统里显示乱码。打开注册表发现的确是乱码。这就排除软件读取得问题,而是调用ChangeServiceConfig系统函数写入时就发生了乱码。让我在网上查找了一下午,都没有结果。主要是我是按照官方的示例创建的呀,既然是官方示例,出现bug的可能就极小。没法,静下心来看官方文档吧。功夫不负有心人,终于让我发现了问题。记录一下错误过程:
出现问题的地方是windows的很多函数都会用宏预先处理调用函数。因为历史的原因,很多函数都会有不同的变种,以自动适配函数和数据类型。比如:ChangeServiceConfig2A 和 ChangeServiceConfig2W 这两个函数,其功能是一样的。主要是数据类型发生了改变。SERVICE_DESCRIPTIONA,SERVICE_DESCRIPTIONW这两中数据类型服务于上面两种不同的函数。
当我们调用ChangeServiceConfig2时,编译器会根据开发环境自动识别选用ChangeServiceConfig2A 或 ChangeServiceConfig2W。我出现问题的地方就是,编译器竟然给我混用了ChangeServiceConfig2A 函数,这个函数是为了兼容以前的老系统版本的,所使用的数据类型是LPSTR。我的开发环境是win11,使用的是LPWSTR数据类型。所以系统显示的配置信息是乱码。
一、 我的开发环境是:windows11 + QT。这是我的开发环境。
二、我按官方示例创建了服务,包括创建、卸载、停止、更新服务配置信息等等。在更新服务配置信息部分出现了写入乱码的问题,下面源码是修正过,运行正确的:
//添加修改服务描述信息
BOOL NpfConfig::SelfChangeServiceConfig(QString m_lpszDriverName, QString m_description)
{SC_HANDLE schManager;SC_HANDLE schService;SERVICE_DESCRIPTIONW lpInfo; LPCWSTR lpszDriverName;LPWSTR description;std::wstring wLpszDriverName = m_lpszDriverName.toStdWString();lpszDriverName = wLpszDriverName.c_str();std::wstring wDescription = m_description.toStdWString();description = wDescription.data();lpInfo.lpDescription = description;qDebug()<<lpInfo.lpDescription;schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (NULL == schManager){return FALSE;}schService = OpenService(schManager, lpszDriverName, SERVICE_ALL_ACCESS);if (NULL == schService){CloseServiceHandle(schManager);return FALSE;}if (!ChangeServiceConfig2W(schService,SERVICE_CONFIG_DESCRIPTION,&lpInfo)){qDebug()<<"修改服务描述信息错误:"<<GetLastError();return false;}else{qDebug()<<"修改服务描述信息成功!";}CloseServiceHandle(schService);CloseServiceHandle(schManager);return true;}
三、这是读取服务配置信息的函数。修正过,可以正常运行的。需要说明的是,上面的代码和下面的代码所用到的数据类型必须一致。我所出现的问题就是相信了编译器给我预处理的选择。最后我手动指定所用函数,而不是让编译器推荐的宏通用函数。
//查询服务描述项
BOOL NpfConfig::DoQueryDescription(QString m_serviceName)
{DWORD dwBytesNeeded, cbBufSize=0, dwError;LPSERVICE_DESCRIPTIONW lpsd;LPWSTR serviceName;std::wstring wServiceName = m_serviceName.toStdWString();serviceName = wServiceName.data();// 打开服务控制管理器数据库SC_HANDLE schSCManager = OpenSCManager(NULL, // 目标计算机的名称,NULL:连接本地计算机上的服务控制管理器NULL, // 服务控制管理器数据库的名称,NULL:打开 SERVICES_ACTIVE_DATABASE 数据库SC_MANAGER_ALL_ACCESS // 所有权限);if (schSCManager == NULL) {CloseServiceHandle(schSCManager);qDebug()<<"服务开启时,服务管理器打开失败"<<GetLastError();return FALSE;}// 打开服务SC_HANDLE schService = OpenService(schSCManager, // 服务控件管理器数据库的句柄serviceName, // 要打开的服务名SERVICE_ALL_ACCESS // 服务访问权限:所有权限);if (schService == NULL) {CloseServiceHandle(schService);CloseServiceHandle(schSCManager);qDebug()<<"服务打开失败"<<GetLastError();return FALSE;}else{qDebug()<<"开启成功:开启服务返回得结果:"<<schService;}lpsd = (LPSERVICE_DESCRIPTIONW) LocalAlloc(LMEM_FIXED, cbBufSize);if( !QueryServiceConfig2(schService,SERVICE_CONFIG_DESCRIPTION,NULL,0,&dwBytesNeeded)){dwError = GetLastError();if( ERROR_INSUFFICIENT_BUFFER == dwError ){cbBufSize = dwBytesNeeded;lpsd = (LPSERVICE_DESCRIPTIONW) LocalAlloc(LMEM_FIXED, dwBytesNeeded);}else{qDebug()<<"QueryServiceConfig2 failed:"<<dwError;}}if (!QueryServiceConfig2(schService,SERVICE_CONFIG_DESCRIPTION,(LPBYTE) lpsd,cbBufSize,&dwBytesNeeded) ){qDebug()<<"QueryServiceConfig2 failed:"<<GetLastError();}else{qDebug()<<"QueryServiceConfig2 获取得描述信息:"<<lpsd->lpDescription;qDebug()<<"QueryServiceConfig2 获取得描述信息:"<<QString::fromStdWString(lpsd->lpDescription);}LocalFree(lpsd);CloseServiceHandle(schService);CloseServiceHandle(schSCManager);return true;
}
相关文章:

windows创建服务:更新服务信息乱码问题(ChangeServiceConfig)
因为小项目需要创建windows服务,安装微软官方示例一切都挺顺利,代码运行后发现配置的信息在系统里显示乱码。打开注册表发现的确是乱码。这就排除软件读取得问题,而是调用ChangeServiceConfig系统函数写入时就发生了乱码。让我在网上查找了一…...

Spark 9:Spark 新特性
Spark 3.0 新特性 Adaptive Query Execution 自适应查询(SparkSQL) 由于缺乏或者不准确的数据统计信息(元数据)和对成本的错误估算(执行计划调度)导致生成的初始执行计划不理想,在Spark3.x版本提供Adaptive Query Execution自适应查询技术,通过在”运行…...

Angular+html+js前端加载生命周期
参考:document.readyState - Web API 接口参考 | MDN (mozilla.org) 第一步,JS生命周期第一步 文档加载中状态,document.readyState loading 第二步,JS生命周期第二步 可交互状态,document.readyState interacti…...

社区投稿| 以安全视角,深度剖析 Sui Staking 与 LSD
本篇技术研报由 MoveBit 研究团队的 Jason 撰写 #1 Sui Staking 介绍 1.1 Sui 网络概述 Sui 网络由一组独立的验证者运行,每个验证者在自己的机器或集群上运行独立的 Sui 软件实例。 Sui 采用委托权益证明(DPoS)来确定哪些验证者参与网络…...

AM@邻域@极限定义中的符号说明
文章目录 abstract邻域👺邻域中心和半径去心邻域 ϵ , δ \epsilon,\delta ϵ,δ的意义各种极限定义的共同点几何意义极限定义中的极限过程临界值 ϵ \epsilon ϵ的选取👺 概念辨析👺无限接近不同于越来越接近例例 越来越接近推不出无限接近 …...

论Oracle兼容性,我们需要做什么
作者介绍:王海峰,数据库系统架构师,YashanDB SQL开发负责人,10年以上数据库内核技术开发经验。 Oracle兼容性是目前国产数据库的关键任务之一,其直接影响到商业迁移的成本和竞争力。 我们经常发现,部分国产…...

你知道多号发圈的同时并延迟评论的方式吗?
你知道多号发圈的同时并延迟评论的方式吗? 其实很简单。 步骤1:编辑好朋友圈内容 步骤2:设置延迟评论 步骤3:选择多个号发圈 通过以上3个步骤,就可以实现多号发圈的同时并延迟评论。 在发布朋友圈前,只需要…...

【BugBounty】记一次XSS绕过
前言 最近一直在看国外的赏金平台,绕waf是真的难受, 记录一下绕过的场景。 初步测试 一开始尝试XSS,发现用户的输入在title中展示,那么一般来说就是看能否闭合,我们从下面图中可以看到,输入尖括号后被转成了实体。 …...

Linux文件目录结构详解:根目录和常见子目录介绍
文章目录 引言1. 什么是Linux文件目录结构2. Linux文件系统的重要性 根目录(/)2.1 根目录的作用和特点2.2 根目录下常见目录的介绍 /bin 目录3.1 /bin 目录的作用和内容3.2 常见的可执行命令示例 /etc 目录4.1 /etc 目录的作用和内容4.2 配置文件的存放位…...

知识付费小程序的推广与用户增长策略
在知识付费小程序开发完成后,推广和用户增长是关键的成功因素。本文将探讨一些推广策略和用户增长方法,并提供代码示例,帮助您在知识付费小程序中实施这些策略。 1. 社交媒体分享功能 在知识付费小程序中添加社交媒体分享功能,…...

微信小程序 获取当前屏幕的可见高宽度
很多时候我们做一下逻辑 需要用整个窗口的高度或宽度参与计算 而且很多时候我们js中拿到的单位都是px像素点 没办法和rpx同流合污 官方提供了wx.getSystemInfoSync() 可以获取到部分窗口信息 其中就包括了整个窗口的宽度和高度 wx.getSystemInfoSync().windowHeight 返回值为像…...

使用 Splashtop 驾驭未来媒体和娱乐
在当今时代,数字转型不再是可选项,而是必选项。如今,媒体与娱乐业处于关键时刻,正在错综复杂的创意、技术和远程协作迷宫之中摸索前进。过去几年发生的全球事件影响了我们的日常生活,不可逆转地改变了行业的运作方式&a…...

Tomcat项目启动报错
java.io.IOException: java.lang.ClassCastException: Cannot cast org.springframework.web.SpringServletContainerInitializer to javax.servlet.ServletContainerInitializer解决办法:可能Tomcat版本不对,使用7.0.90版本启动报错,使用8.0…...

offer
【录用通知书】 如何判断公司的好坏呢。 注意了,我们软件行业,技术管理类,技术类,产品类 好公司好企业基本都会给你说清楚,一项多少钱,加班多少钱,这样的 像这类公司的薪资结构复杂就要特别…...

漏洞复现--鸿运主动安全监控云平台任意文件下载
免责声明: **文章中涉及的漏洞均已修复,敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何…...

第二章 物理层 | 计算机网络(谢希仁 第八版)
文章目录 第二章 物理层2.1 物理层的基本概念2.2 数据通信的基础知识2.2.1 数据通信系统的模型2.2.2 有关信道的几个基本概念2.2.3 信道的极限容量 2.3 物理层下面的传输媒体2.3.1 导引型传输媒体2.3.2 非导引型传输媒体 2.4 信道复用技术2.4.1 频分复用、时分复用和统计时分复…...

路由高级特性
项目拓扑与项目需求 项目需求 某企业网络使用ospf和isis作为IGP协议实现内部网络的互联互通,区域规划和IP规划如图所示,现在要求实现如下需求: LSW1和AR1使用vlan10互联,与AR2使用vlan20互联,LSW1与LSW2、3、4之间使…...

【MySQL】数据库排查慢查询、死锁进程排查、预防以及解决方法
MySQL数据库排查慢查询、死锁进程及解决方法 一、排查慢查询 1.1检查慢查询日志是否开启 1.1.1使用命令检查是否开启慢查询日志: SHOW VARIABLES LIKE slow_query_log;如果是 Value 为 off 则并未开启 1.1.2开启并且查看慢查询日志: MySQL提供了慢查询日志功能,可以记录所…...

WSL2下的Docker配置和使用
在Windows的Linux子系统(Windows Subsystem for Linux)WSL2中安装、配置和使用 Docker,可以参考官方教程:WSL上的Docker远程容器入门. 重要步骤总结如下: 先决条件 确保你的计算机运行的是 Windows 10(更…...

污水管网水位监测,管网水位监测仪守护城市污水管网运行
万宾科技:污水管网水位监测 近年来,城市化进程的加速使得污水管网建设愈发重要。然而,在管网运维中,水位监测一直以来都是一个令人头痛的难题。为了解决这一问题,万宾科技公司推出了管网水位监测仪EN200-D2࿰…...

IDEA插件版本升级和兼容新版本idea
1.关于IDEA插件的版本设置问题 打开jetbrains插件市场,随意打开一个插件详情页面的Versions菜单,我们可以看见一个插件包不同时期发布的不同版本(Versions),并且每个版本包含了可兼容IDEA或PyCharm的版本范围…...

Docker 容器应急
容器网络简单理解 容器拥有n多张veth网卡与一张docker0网卡 docker 五种网络 bridge 默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。host 容器不会获得一个独立的network namespace,而是与宿主机共用一个…...

webservice接口自动化测试
1,用soupui进行测试 2,安装soupUI 3,测试的时候是给了一个wdsl 操作步诹:new (name , 填写地址)---导入wsdl文件---看到所有的接口 发送请求的格式<xml> canshu</xml> 应用场景,…...

精益生产与MES生产管理系统相互融合
近年来,精益生产理念在企业管理中越来越受欢迎。它强调以最小的浪费,在最短的时间内,生产出高质量的产品。这一理念的实施手段包括准时制生产方式、适时生产方式等,消除浪费、看板、快换工装等都是精益提高的工具方针。 然而&…...

(c语言进阶)指针的进阶
一.字符指针 1.一般应用 (1)%c的应用 (2)%s的应用 字符指针没有权限通过解引用去改变指针指向的值 2.笔试题 题目:判断输出结果 int main() { const char* p1 "abcdef"; const char* p2 "…...

用路由器远程维护三菱PLC操作指南
用路由器远程维护三菱PLC操作指南...

FPGA面试题(7)
一.解释一下SPI的四种模式 01时钟极性CPOL空闲状态为低电平空闲状态为高电平时钟相位CPHA在第一个跳变沿采样在第二个跳变沿采样 模式CPOLCPHA描述模式000sclk上升沿采样,sclk下降沿发送模式101sclk上升沿发送,sclk下降沿采样模式210sclk上升沿发送&…...

Python接口自动化测试之【测试函数、测试类/测试方法的封装】
前言 在pythonpytest 接口自动化系列中,我之前的文章基本都没有将代码进行封装,但实际编写自动化测试脚本中,我们都需要将测试代码进行封装,才能被测试框架识别执行。 例如单个接口的请求代码如下: import requests…...

ROS仿真软件Turtlebot-Gazebo的安装使用以及错误处理[机器人避障]
很多时候由于机器人价格比较贵,而且会因为环境因素、操作失误或者摔坏等,所以我们可以先在仿真软件上做测试,也可以避免这些问题,虽然没有那么真实感,可毕竟是免费的嘛。我们可以在这些仿真的机器人身上去学习如何控制…...

把excel文件内容转化为json文件
js如何把excel文件转化为json文件呢?可以通过xlsx还有循环遍历来做 第一步:安装xlsx包 npm install xlsx这里我需要转化为这种类型 {key:value,key:value,key:value, }如果需要转化为其他格式,到时候需要在循环遍历的时候灵活运用 上代码…...