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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开软古剑楠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值