windows创建服务:更新服务信息乱码问题(ChangeServiceConfig)

news2024/11/18 2:48:36

        因为小项目需要创建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;
}

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

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

相关文章

1.4python 引入其他 py 文件或模块_python量化实用版教程(初级)

python 引入其他 py 文件或模块 在 Python 中&#xff0c;我们可以使用 import 语句来引用其他 py 文件中的代码&#xff0c;这样可以避免代码的重复编写&#xff0c;提高代码的复用性和可维护性。 引用其他 py 文件的方式 Python 提供了多种方式来引用其他 py …

Nginx部署前端网页,Nginx搭建静态资源服务器

文章目录 一、准备静态网页二、安装nginx三、部署网页四、显示文件及文件夹目录信息 一、准备静态网页 我们以dlib静态网页为例&#xff0c;使用nginx部署前端网页&#xff1a; 下载地址&#xff1a;http://dlib.net/ 下载完成之后上传至linux服务器。 在docs目录下&#xff…

在 Elasticsearch 中实现自动完成功能 3:completion suggester

在这篇博文中&#xff0c;我们将讨论 complete suggester - 一种针对自动完成功能进行优化的 suggester&#xff0c;并且被认为比我们迄今为止讨论的方法更快。 Completion suggester 使用称为有限状态转换器的数据结构&#xff0c;该结构类似于 Trie 数据结构&#xff0c;并且…

PIM基础

1.PIM概述 PIM协议简介 PIM称为协议无关组播。协议无关指的是与单播路由协议无关&#xff0c;即PIM不需要维护专门的单播路由信息。作为组播路由解决方案&#xff0c;它直接利用单播路由表的路由信息&#xff0c;对组播报文执行RPF检查&#xff0c;检查通过后创建组播路由表项…

《Java极简设计模式》第08章:外观模式(Facade)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

conda 创建虚拟环境

1.为什么要创建虚拟环境 我们在做开发或者跑论文实验可能会同时进行多个任务&#xff0c;这些任务可能会依赖于不同的python环境&#xff0c;比如有的用到3.6有的用到3.7&#xff0c;这时我们创建不同版本的python&#xff0c;放到虚拟环境中给不同的任务分别提供其所需要的版本…

Docker简单案例

我们安装完Docker之后就可以练习了. 镜像 案例1-拉取、查看镜像 1&#xff09;首先去镜像仓库搜索nginx镜像&#xff0c;比如 : Docker Hub Container Image Library | App Containerization 搜索我们想要拉取的镜像 , 例如: nginx 复制命令&#xff1a; docker pull nginx …

【智慧燃气】中国智慧燃气现状、关键问题分析及构架分析!

关键词&#xff1a;智慧燃气、数据分析、数据挖掘、数字燃气、智慧燃气平台 一、智慧燃气发展现状 智慧燃气概述 对于智慧燃气的概念&#xff0c;燃气行业目前并未有统一的定义&#xff0c;基本上还处于各自阐述的阶段。小编认为&#xff0c;城乡智慧燃气系统&#xff08;以…

400电话号码办理

办理400虚拟电话号码的需求在如今的商业环境中越来越普遍。无论是小型企业还是个人创业者&#xff0c;拥有自己的400虚拟电话号码都能为他们的业务带来巨大的便利和形象提升。那么&#xff0c;如何高效地办理400虚拟电话号码呢&#xff1f; 首先&#xff0c;选择可信赖的服务提…

干货:如何在前端统计用户访问来源?

在前端统计用户访问来源是一个常见的需求&#xff0c;通过获取访问来源信息&#xff0c;我们可以了解用户是通过直接访问、搜索引擎、外部链接等途径进入我们的网站或应用。下面是一个详细的介绍&#xff0c;包括方法和实现步骤。 一、获取HTTP Referer HTTP Referer是HTTP请…

使用XLua在Unity中获取lua全局变量和函数

1、Lua脚本 入口脚本 print("OK") --也会执行重定向 require("Test") 测试脚本 print("TestScript") testNum 1 testBool true testFloat 1.2 testStr "123"function testFun()print("无参无返回") endfunction te…

力扣 -- 1312. 让字符串成为回文串的最少插入次数

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int minInsertions(string s) {int ns.size();vector<vector<int>> dp(n,vector<int>(n));//无需初始化//填表for(int in-1;i>0;i--){for(int ji;j<n;j){//状态转移方程if(s[i]s[…

【MySQL】数据库排查慢查询、死锁进程排查、预防以及解决方法

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

文件系统和文件读写(初识)

1.文件读写 1.QFileDialog提供了一个对话框&#xff0c;允许用户选择文件或者目录&#xff0c;也允许用户遍历文件系统&#xff0c;用以选择一个或多个文件或者目录。 2.QFileDialog继承了QDialog&#xff0c;具有父类的各种方法 3.Qt QFile文件操作 很多应用程序都需要具备…

centos7下 编译coreboot生成真机可用的bios固件, 并在真机上演示 (上篇)

看了国内的corebot相关文章以及b站的corebot视频, 大不部分都是编译 用于虚拟机(qemu)或者模拟器上运行的 很少有编译corebot项目 出可以再真机上使用的的 bios 本教程应该是全网最详细的了, 真机版的coreboot bios固件, 所以有点长, 希望对你有帮助 #coreboot编译总说明文档…

寒冬之下,互联网金融的数据化建设心得

引言&#xff1a; 在当前经济寒冬下&#xff0c;互联网金融行业面临着巨大的竞争压力和市场变化。为了保持竞争优势&#xff0c;不断创新和适应市场需求&#xff0c;互联网金融企业需要进行数据化建设。 本文将从策略规划、数据采集与整合、数据挖掘与分析、风险控制等方面&a…

数学建模——确定性时间序列分析方法

介绍 将预测对象按照时间顺序排成一组序列&#xff0c;称为时间序列。从时间序列过去的变化规律&#xff0c;推断今后变化的可能性及变化趋势、变化规律&#xff0c;这就是时间序列预测法。 时间序列模型&#xff0c;其实也是一种回归模型。其基本原理是&#xff0c;一方面承认…

windows Vscode 连接 虚拟机,超详细,含免密免ip配置 以 linux 虚拟机为例

我们这里使用 ssh 进行连接&#xff0c;不了解 ssh 的也没关系&#xff0c;感兴趣的可以自己了解一下。 我的虚拟机是 Ubuntu20.04&#xff0c;如果出现与 Centos 不一样的操作可以自行替换。 &#xff08;应该不会有&#xff1f;&#xff1f;&#xff09; 一 . 登录虚拟机~&a…

植物转录因子研究策略及方法

植物转录因子研究 转录因子&#xff08;TF&#xff09;是一类具有特殊结构的蛋白质&#xff0c;也称为反式作用因子。通过与靶基因启动子区域的顺式作用元件特异性结合&#xff0c;行使调控基因表达的功能。典型的转录因子一般具有4个功能结构域&#xff1a;DNA结合区&#xf…

pyqt 划线标注工具,可用于车道线标注

目录 效果图: pyqt代码: opencv划线: 效果图: pyqt代码: import osfrom PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton, QLabel from PyQt5.QtGui import QPainter, QPen, QColor, QImage, QPixmap from PyQt5.QtCore import Qt, QPoint i…