gpt4 book ai didi

c++ - 使用 Windows API 写入和读取 Windows 注册表

转载 作者:行者123 更新时间:2023-11-30 01:38:12 24 4
gpt4 key购买 nike

我正在尝试从 Windows 寄存器写入和读取:

写作:

std::string path = "c:\\"
LPCTSTR str_data = TEXT(path.c_str());
auto size = static_cast<DWORD>(strlen(str_data));
LONG setRes = RegSetValueEx(*key, TEXT("DumpFolder"), 0, REG_EXPAND_SZ, (LPBYTE)str_data, size);

阅读:

char str_data[1028];
DWORD keyType;
DWORD size;
auto sk = TEXT("SOFTWARE\\Microsoft\\Windows\\Windows Error reporting\\LocalDumps");
auto status = RegGetValue(HKEY_LOCAL_MACHINE, sk, TEXT("DumpFolder"), RF_RT_REG_EXPAND_SZ, &keyType, str_data, &size);

写入似乎工作正常,至少在 regedit.exe 中看起来不错。

读取失败,ERROR_INVALID_PARAMETER = 87。如果我将 RF_RT_REG_EXPAND_SZ 更改为 RRF_RT_ANY,它可以在 Debug模式下工作,但在发布时仍然失败,错误代码为 ERROR_MORE_DATA = 234。我试过:

std::string path = "c:\\";
path = path + "\0" (it should be null terminated anyway

但没用

更新

首先,感谢您的回答,我现在对事情的理解好多了。不幸的是,我仍然无法成功读取字符串。

下面是结合以下答案的测试示例:

HKEY registry_key;
LPCTSTR sk = "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting";

// open registry key
auto openRes = RegOpenKey(HKEY_CURRENT_USER, sk, &registry_key);

// set default dump options
HKEY default_key;
auto createRes = RegCreateKey(registry_key, "LocalDumps", &default_key);
if (createRes != ERROR_SUCCESS) {
auto b = createRes;
}

std::string path = "c:\\";
LONG setRes = RegSetValueExA(default_key, "DumpFolder", 0, REG_EXPAND_SZ, (LPCBYTE)path.c_str(), path.size() + 1);

std::string str_data;
DWORD size = 0;
const char *sak = "SOFTWARE\\Microsoft\\Windows\\Windows Error reporting\\LocalDumps";
auto status = RegGetValueA(HKEY_CURRENT_USER, sak, "DumpFolder", RRF_RT_REG_EXPAND_SZ, NULL, NULL, &size);
if ((status == ERROR_SUCCESS) && (size > 1)) {
str_data.resize(size - 1);
status = RegGetValueA(HKEY_CURRENT_USER, sk, "DumpFolder", RRF_RT_REG_EXPAND_SZ, NULL, &str_data[0], &size);
}

再次写入工作正常(在 regedit 中检查,并返回错误代码)。另一方面,读取字符串寄存器的大小会将大小设置为 0 并返回错误代码 87 = ERROR_INVALID_PARAMETER。

显然,我仍然缺少一些东西。 (项目设置为多字节字符集)

解决方案

在修复了以下答案提出的问题后,以下代码对我有用:

#include <Windows.h>
#include <string>
#include <iostream>

#define reg_type HKEY_LOCAL_MACHINE

void main() {

const std::string reg_path = "Software\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps";
const std::string dump_folder = "DumpFolder";
const std::string path = "c:\\";

// WRITING
HKEY default_key;
auto status = RegCreateKeyExA(reg_type, reg_path.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_QUERY_VALUE, NULL, &default_key, NULL);
if (status != ERROR_SUCCESS) {
std::cout << "Creating key failed.";
return;
}
status = RegSetValueExA(default_key, dump_folder.c_str(), 0, REG_EXPAND_SZ, (LPCBYTE)path.c_str(), path.size() + 1);
if (status != ERROR_SUCCESS) {
std::cout << "Setting key value failed.";
return;
}

// READING
std::string str_data;
DWORD size = 0;
status = RegGetValueA(default_key, "", dump_folder.c_str(), RRF_NOEXPAND | RRF_RT_REG_EXPAND_SZ, NULL, NULL, &size);
if ((status == ERROR_SUCCESS) && (size > 1)){
str_data.resize(size - 1);
status = RegGetValueA(default_key, "", dump_folder.c_str(), RRF_NOEXPAND | RRF_RT_REG_EXPAND_SZ, NULL, &str_data[0], &size);
std::cout << "Successfully read key value: " << str_data;
} else {
std::cout << "Unable to retrive value. Error: " << status;
}

RegCloseKey(default_key);
}

我发现,应该用

调用 RegGetValueA
RRF_NOEXPAND | RRF_RT_REG_EXPAND_SZ 

标志,看起来很奇怪,但在定义它的标题中有描述,所以我猜它是正确的。如果仅使用

RRF_RT_REG_EXPAND_SZ

发生错误 87 ERROR_INVALID_PARAMETER。

最佳答案

在写作方面:

std::string 使用 char 元素,但 TCHAR 映射到 charwchar_t 取决于您的代码是否使用定义的 UNICODE 进行编译。

TEXT() 宏仅适用于编译时文字,不能用于运行时数据TEXT(path.c_str()) 是无效的类型转换,如果启用了 UNICODE 甚至无法编译。

您显然正在使用 char 数据,因此您应该使用基于 char 的 API 函数而不是基于 TCHAR 的函数.

您也没有遵循 RegSetValueEx() 的最重要规则之一:

For string-based types, such as REG_SZ, the string must be null-terminated. With the REG_MULTI_SZ data type, the string must be terminated with two null characters... The size of the information pointed to by the lpData parameter, in bytes. If the data is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ, cbData must include the size of the terminating null character or characters.

std::string::c_str() 返回一个指向以 null 终止的数据的指针,但在报告您写入注册表的数据大小时,您不包括 null 终止符。 RegGetValue() 知道如何处理该错误,但 RegGetValueEx() 不知道。您可能不是唯一读取该值的人,因此请确保正确包含空终止符。

试试这个:

std::string path = "c:\\";
LONG setRes = RegSetValueExA(*key, "DumpFolder", 0, REG_EXPAND_SZ, (LPCBYTE)path.c_str(), path.size()+1);

在阅读方面:

您收到错误是因为您没有告诉 RegGetValue() 您的 str_data 缓冲区有多大。在传入之前,您必须将 size 变量设置为 str_data 的大小(以字节为单位)。

试试这个:

char str_data[1028];
DWORD size = sizeof(str_data);
DWORD dwFlags = RRF_RT_REG_EXPAND_SZ;
// NOTE: when using RRF_RT_REG_EXPAND_SZ, RRF_NOEXPAND is *required* prior to Windows 8.1!
auto status = RegGetValueA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\Windows Error reporting\\LocalDumps", "DumpFolder", RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, NULL, str_data, &size);

或者:

std:string str_data;
DWORD size = 0;
const char *sk = "SOFTWARE\\Microsoft\\Windows\\Windows Error reporting\\LocalDumps";
// NOTE: when using RRF_RT_REG_EXPAND_SZ, RRF_NOEXPAND is *required* prior to Windows 8.1!
const DWORD dwFlags = RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND;
auto status = RegGetValueA(HKEY_LOCAL_MACHINE, sk, "DumpFolder", dwFlags, NULL, NULL, &size);
if ((status == ERROR_SUCCESS) && (size > 1))
{
str_data.resize(size-1);
status = RegGetValueA(HKEY_LOCAL_MACHINE, sk, "DumpFolder", dwFlags, NULL, &str_data[0], &size);
}

更新:您的新代码失败,因为您引入了新错误。

您正在使用适用于 16 位应用程序的旧注册表功能。您需要使用RegOpenKeyEx/RegCreateKeyEx而不是RegOpenKey/RegCreateKey,然后您可以只指定特定的访问权限您实际需要的权限(创建子项、设置值、读取值等)。更好的是,RegCreateKeyEx() 会为您创建丢失的 key ,因此您无需单独手动打开父 key 来创建新的子 key 。

此外,您将 HKEY_LOCAL_MACHINE 更改为 HKEY_CURRENT_USER,但并不一致。您的某些步骤使用一个根,其他步骤使用另一个根。您无法读回您正在写入的值,因为您没有从您写入的同一个键读取。

试试这个:

LPCSTR sk = "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps";
HKEY default_key;
auto status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, sk, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &default_key, NULL);
if (status == ERROR_SUCCESS)
{
std::string path = "c:\\";
status = RegSetValueExA(default_key, "DumpFolder", 0, REG_EXPAND_SZ, (LPCBYTE)path.c_str(), path.size() + 1);
RegCloseKey(default_key);
}

LPCSTR sk = "SOFTWARE\\Microsoft\\Windows\\Windows Error reporting\\LocalDumps";
std::string str_data;
DWORD size = 0;
// NOTE: when using RRF_RT_REG_EXPAND_SZ, RRF_NOEXPAND is *required* prior to Windows 8.1!
const DWORD dwFlags = RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND;
auto status = RegGetValueA(HKEY_LOCAL_MACHINE, sk, "DumpFolder", dwFlags, NULL, NULL, &size);
if ((status == ERROR_SUCCESS) && (size > 1))
{
str_data.resize(size - 1);
status = RegGetValueA(HKEY_LOCAL_MACHINE, sk, "DumpFolder", dwFlags, NULL, &str_data[0], &size);
}

另一方面,当你必须进行多次API调用来读取一个值时(即查询大小,然后查询数据),你应该首先显式打开父键:

const char *sk = "SOFTWARE\\Microsoft\\Windows\\Windows Error reporting\\LocalDumps";
std:string str_data;
HKEY default_key;
auto status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, sk, 0, KEY_QUERY_VALUE, &dumps_key);
if (status == ERROR_SUCCESS)
{
DWORD size = 0;
// NOTE: when using RRF_RT_REG_EXPAND_SZ, RRF_NOEXPAND is *required* prior to Windows 8.1!
const DWORD dwFlags = RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND;

status = RegGetValueA(default_key, "", "DumpFolder", dwFlags, NULL, NULL, &size);
if ((status == ERROR_SUCCESS) && (size > 1))
{
str_data.resize(size-1);
status = RegGetValueA(default_key, "", "DumpFolder", dwFlags, NULL, &str_data[0], &size);
}

RegCloseKey(default_key);
}

关于c++ - 使用 Windows API 写入和读取 Windows 注册表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48428728/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com