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࿰…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
