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

C++Builder 11.1.5:TRegistry恢复HKEY_LOCAL_MACHINE注册表项失败求助

注册表恢复失败排查(C++Builder 11.1.5 VCL 64位)

开发Windows VCL 64位应用时,已通过SetPrivilege开启SE_BACKUP_NAME权限,成功用TRegistry::SaveKey备份HKEY_LOCAL_MACHINE\Software下的注册表项,但调用TRegistry::LoadKey恢复时始终返回false失败。

备份代码:

void SaveRegistryKeyToFile(const UnicodeString& key, const UnicodeString& fileName)
{
    TRegistry *reg=new TRegistry(KEY_READ);
    HANDLE ProcessToken;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
        SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
        TRegistry *reg=new TRegistry(KEY_READ);
        reg->RootKey=HKEY_LOCAL_MACHINE;
        reg->SaveKey(key,fileName);
        delete reg;
    }
}

恢复代码:

void LoadRegistryKeyFromFile(const UnicodeString& key, const UnicodeString& fileName)
{
    TRegistry *reg;
    HANDLE ProcessToken;
    bool Result;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
        SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
        reg = new TRegistry(KEY_WRITE)
        reg->RootKey=HKEY_LOCAL_MACHINE;
        if(FileExists(fileName)) {
            Result = reg->LoadKey(key,fileName);
        }
        delete reg;
    }
}

排查与解决方向

1. 权限类型错误:恢复需SE_RESTORE_NAME而非SE_BACKUP_NAME

SaveKey依赖SE_BACKUP_NAME权限,但LoadKey要求的是**SE_RESTORE_NAME权限**,替换权限类型即可:

SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE);

2. 注册表访问权限不足

恢复时TRegistry仅用KEY_WRITE权限不够,需要包含KEY_CREATE_SUB_KEY,建议扩展权限组合:

reg = new TRegistry(KEY_WRITE | KEY_CREATE_SUB_KEY);

同时要确保目标父项已存在——LoadKey要求待恢复子项的父注册表项必须预先存在(比如要恢复HKEY_LOCAL_MACHINE\Software\MyApp,需确保HKEY_LOCAL_MACHINE\Software已存在)。

3. 64位系统注册表重定向问题

64位应用默认会访问HKEY_LOCAL_MACHINE\Software\Wow6432Node(32位分支),如果备份的是原生64位注册表分支,需强制禁用重定向:

reg = new TRegistry(KEY_WRITE | KEY_CREATE_SUB_KEY);
reg->Access = reg->Access | KEY_WOW64_64KEY; // 强制访问64位注册表分支

4. 代码语法错误

恢复代码中reg = new TRegistry(KEY_WRITE)末尾缺少分号,会导致编译错误,修正为:

reg = new TRegistry(KEY_WRITE);

5. 文件路径与权限问题

  • 确保备份文件路径为绝对路径,避免相对路径导致文件找不到;
  • 当前进程需拥有备份文件的读取权限,避免放在系统目录(如C:\Windows)下,除非应用以管理员身份运行。

6. 错误码定位问题

调用LoadKey失败后,通过GetLastError()获取具体系统错误码,精准定位问题:

Result = reg->LoadKey(key,fileName);
if(!Result){
    DWORD err = GetLastError();
    // 根据错误码排查:比如5=权限拒绝,2=文件不存在,123=文件名无效等
}

修正后的恢复代码示例

void LoadRegistryKeyFromFile(const UnicodeString& key, const UnicodeString& fileName)
{
    TRegistry *reg = nullptr;
    HANDLE ProcessToken = nullptr;
    bool Result = false;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
        // 恢复使用SE_RESTORE_NAME权限
        SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE);
        // 组合必要权限并强制访问64位注册表
        reg = new TRegistry(KEY_WRITE | KEY_CREATE_SUB_KEY | KEY_WOW64_64KEY);
        reg->RootKey = HKEY_LOCAL_MACHINE;
        if(FileExists(fileName)) {
            Result = reg->LoadKey(key, fileName);
            if(!Result){
                DWORD err = GetLastError();
                // 可添加错误日志或用户提示
            }
        }
        delete reg;
        CloseHandle(ProcessToken); // 关闭令牌句柄避免资源泄漏
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:32:04