调用C++Builder的TRegistry::SaveKey()后为何生成的文件不存在?
解决TRegistry::SaveKey()无错误但快照文件缺失的问题
以下是针对你代码中导致快照文件无法生成的核心问题及修正方案:
1. SaveKey参数传递错误
TRegistry::SaveKey的第一个参数是相对于当前已打开键的子键路径,而非完整注册表路径。你已经通过OpenKey(WinKey, false)打开了目标键,此时要保存当前打开的整个键,应传入空字符串L"",而非完整的WinKey路径。原代码传入完整路径会导致SaveKey尝试保存不存在的子键,最终无文件生成。
2. 权限不足
调用SaveKey需要程序拥有SE_BACKUP_NAME权限,普通用户权限无法完成注册表键备份操作。你需要:
- 右键程序,选择「以管理员身份运行」;
- 或在项目设置中添加UAC清单,让程序默认请求管理员权限。
3. 目标目录需提前存在
fPath指向的S:\FOE\Keys目录必须提前创建,否则SaveKey无法自动创建父目录,会静默失败(部分场景下LastError不会返回错误码)。
修正后的代码
#define ROOTKEY HKEY_USERS void __fastcall TOptionsForm::SnapShot(void) { TRegistry *WinReg; UnicodeString WinKey; UnicodeString fPath; UnicodeString msg; fPath.sprintf(L"S:\\FOE\\Keys\\FileExts"); // 确保父目录存在 if (!DirectoryExists(ExtractFileDir(fPath))) { ForceDirectories(ExtractFileDir(fPath)); } // 使用SaveKey所需的最小权限,避免不必要的权限请求 WinReg = new TRegistry(KEY_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY); WinReg->RootKey = ROOTKEY; WinKey.sprintf(L"S-1-5-21-192366507-594344067-2320108307-1001\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts"); if (WinReg->OpenKey(WinKey,false)) { ListBox1->Items->Add(fPath); // 传入空字符串,保存当前打开的整个注册表项 bool saveResult = WinReg->SaveKey(L"", fPath); // 优先检查SaveKey返回值,比依赖LastError更可靠 if (!saveResult) { msg.sprintf(L"Error %d",WinReg->LastError); ListBox1->Items->Add(msg); msg = WinReg->LastErrorMsg; ListBox1->Items->Add(msg); } else { ListBox1->Items->Add(L"快照保存成功"); } WinReg->CloseKey(); } else { ListBox1->Items->Add(L"无法打开目标注册表项"); msg.sprintf(L"Error %d",WinReg->LastError); ListBox1->Items->Add(msg); } delete WinReg; }
额外注意事项
- 避免使用
KEY_ALL_ACCESS,这会请求不必要的高权限,可能导致注册表项打开失败,改用所需最小权限即可; - 优先检查
SaveKey的返回值,而非仅依赖LastError,部分操作失败场景下LastError不会及时更新; - 确认目标路径所在磁盘有写入权限,若S盘是网络映射盘,需验证写入权限是否正常。
内容的提问来源于stack exchange,提问作者Nigel Stevens
相关产品推荐
相关产品推荐

