You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中为已注册Windows服务添加依赖并保留RPCSS依赖?

在C++中修改Windows服务依赖(保留现有RPCSS依赖)

要实现版本切换后动态添加服务依赖且不丢失原有RPCSS依赖,核心是通过Windows服务控制API先读取现有依赖,再合并新依赖后写入,而非直接覆盖。以下是具体实现步骤和代码示例:

实现步骤

  1. 打开目标服务:申请SERVICE_CHANGE_CONFIG(修改配置)和SERVICE_QUERY_CONFIG(查询配置)权限,确保能读取和修改服务依赖。
  2. 读取现有依赖项:通过QueryServiceConfig2函数获取当前服务的依赖列表,包含已有的RPCSS依赖。
  3. 合并新依赖:将现有依赖数组与需要添加的新依赖项合并,保留原有RPCSS不被移除。
  4. 更新服务依赖:调用ChangeServiceConfig2将合并后的依赖列表写入服务配置。

C++代码示例

#include <windows.h>
#include <tchar.h>
#include <vector>
#include <iostream>

bool AddServiceDependency(LPCTSTR szServiceName, LPCTSTR szNewDependency)
{
    // 打开服务控制管理器
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!hSCM)
    {
        _tprintf(_T("OpenSCManager failed, error: %d\n"), GetLastError());
        return false;
    }

    // 打开目标服务,需查询和修改权限
    SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
    if (!hService)
    {
        _tprintf(_T("OpenService failed, error: %d\n"), GetLastError());
        CloseServiceHandle(hSCM);
        return false;
    }

    // 先获取现有依赖的缓冲区大小
    DWORD dwBytesNeeded = 0;
    QueryServiceConfig2(hService, SERVICE_CONFIG_DEPENDENCIES, NULL, 0, &dwBytesNeeded);
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    {
        _tprintf(_T("QueryServiceConfig2 (get size) failed, error: %d\n"), GetLastError());
        CloseServiceHandle(hService);
        CloseServiceHandle(hSCM);
        return false;
    }

    // 分配缓冲区存储现有依赖
    std::vector<BYTE> buffer(dwBytesNeeded);
    LPSERVICE_CONFIG_DEPENDENCIES pDependencies = reinterpret_cast<LPSERVICE_CONFIG_DEPENDENCIES>(buffer.data());
    if (!QueryServiceConfig2(hService, SERVICE_CONFIG_DEPENDENCIES, buffer.data(), dwBytesNeeded, &dwBytesNeeded))
    {
        _tprintf(_T("QueryServiceConfig2 failed, error: %d\n"), GetLastError());
        CloseServiceHandle(hService);
        CloseServiceHandle(hSCM);
        return false;
    }

    // 统计现有依赖数量,同时检查是否已存在目标依赖
    int nExistingCount = 0;
    bool bDepExists = false;
    if (pDependencies->lpDependencies != NULL)
    {
        for (LPTSTR* pDep = pDependencies->lpDependencies; *pDep != NULL; pDep++)
        {
            nExistingCount++;
            if (_tcscmp(*pDep, szNewDependency) == 0)
            {
                bDepExists = true;
                break;
            }
        }
    }

    if (bDepExists)
    {
        _tprintf(_T("Dependency already exists.\n"));
        CloseServiceHandle(hService);
        CloseServiceHandle(hSCM);
        return true;
    }

    // 构建新的依赖数组:现有依赖 + 新依赖 + NULL结尾
    int nNewCount = nExistingCount + 1;
    std::vector<LPTSTR> newDeps(nNewCount + 1, NULL);

    // 复制现有依赖
    if (pDependencies->lpDependencies != NULL)
    {
        for (int i = 0; i < nExistingCount; i++)
        {
            size_t len = _tcslen(pDependencies->lpDependencies[i]) + 1;
            newDeps[i] = reinterpret_cast<LPTSTR>(LocalAlloc(LPTR, len * sizeof(TCHAR)));
            if (!newDeps[i])
            {
                _tprintf(_T("LocalAlloc failed, error: %d\n"), GetLastError());
                // 释放已分配内存
                for (int j = 0; j < i; j++)
                    LocalFree(newDeps[j]);
                CloseServiceHandle(hService);
                CloseServiceHandle(hSCM);
                return false;
            }
            _tcscpy_s(newDeps[i], len, pDependencies->lpDependencies[i]);
        }
    }

    // 添加新依赖
    size_t newDepLen = _tcslen(szNewDependency) + 1;
    newDeps[nExistingCount] = reinterpret_cast<LPTSTR>(LocalAlloc(LPTR, newDepLen * sizeof(TCHAR)));
    if (!newDeps[nExistingCount])
    {
        _tprintf(_T("LocalAlloc for new dependency failed, error: %d\n"), GetLastError());
        for (int j = 0; j < nExistingCount; j++)
            LocalFree(newDeps[j]);
        CloseServiceHandle(hService);
        CloseServiceHandle(hSCM);
        return false;
    }
    _tcscpy_s(newDeps[nExistingCount], newDepLen, szNewDependency);

    // 更新服务依赖
    SERVICE_CONFIG_DEPENDENCIES newServiceDeps;
    newServiceDeps.lpDependencies = newDeps.data();
    if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DEPENDENCIES, &newServiceDeps))
    {
        _tprintf(_T("ChangeServiceConfig2 failed, error: %d\n"), GetLastError());
        for (int j = 0; j < nNewCount; j++)
            LocalFree(newDeps[j]);
        CloseServiceHandle(hService);
        CloseServiceHandle(hSCM);
        return false;
    }

    // 清理资源
    for (int j = 0; j < nNewCount; j++)
        LocalFree(newDeps[j]);
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCM);

    _tprintf(_T("Dependency added successfully.\n"));
    return true;
}

int _tmain(int argc, TCHAR* argv[])
{
    if (argc != 3)
    {
        _tprintf(_T("Usage: %s <ServiceName> <NewDependency>\n"), argv[0]);
        return 1;
    }

    // 需以管理员权限运行
    if (!AddServiceDependency(argv[1], argv[2]))
    {
        return 1;
    }

    return 0;
}

关键注意事项

  • 权限要求:程序必须以管理员权限运行,否则无法修改服务配置。
  • 重复依赖检测:代码内置重复依赖检查,避免重复添加同一依赖项。
  • 错误排查:每个API调用都做了错误捕获,可通过GetLastError()获取具体错误码定位问题。
  • 内存安全:所有分配的字符串内存都做了释放处理,避免内存泄漏。
  • 编码兼容:使用TCHAR系列宏,支持Unicode和ANSI编译环境。

内容的提问来源于stack exchange,提问作者byron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 10:45:19