- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在某些代码中,我使用了 Win32 RegGetValue()
从注册表中读取字符串的 API。
我两次调用上述 API:
第一次调用的目的是获得合适的大小,以便为字符串分配目标缓冲区。
第二次调用从注册表中读取字符串到该缓冲区中。
奇怪的是,我发现 RegGetValue()
在两次调用之间返回了不同大小的值。
特别是,第二次调用返回的大小值比第一次调用小两个字节(相当于一个wchar_t
)。
值得注意的是,与实际字符串长度兼容的大小值是第二次调用返回的值(这个对应实际字符串长度,包括终止NUL
).
但我不明白为什么第一次调用返回的大小比那个大两个字节(一个 wchar_t
)。
附上程序输出截图和Win32 C++可编译重现代码。
重现源代码
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void PrintSize(const char* const message, const DWORD sizeBytes)
{
cout << message << ": " << sizeBytes << " bytes ("
<< (sizeBytes/sizeof(wchar_t)) << " wchar_t's)\n";
}
int main()
{
const HKEY key = HKEY_LOCAL_MACHINE;
const wchar_t* const subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion";
const wchar_t* const valueName = L"CommonFilesDir";
//
// Get string size
//
DWORD keyType = 0;
DWORD dataSize = 0;
const DWORD flags = RRF_RT_REG_SZ;
LONG result = ::RegGetValue(
key,
subKey,
valueName,
flags,
&keyType,
nullptr,
&dataSize);
if (result != ERROR_SUCCESS)
{
cout << "Error: " << result << '\n';
return 1;
}
PrintSize("1st call size", dataSize);
const DWORD dataSize1 = dataSize; // store for later use
//
// Allocate buffer and read string into it
//
vector<wchar_t> buffer(dataSize / sizeof(wchar_t));
result = ::RegGetValue(
key,
subKey,
valueName,
flags,
nullptr,
&buffer[0],
&dataSize);
if (result != ERROR_SUCCESS)
{
cout << "Error: " << result << '\n';
return 1;
}
PrintSize("2nd call size", dataSize);
const wstring text(buffer.data());
cout << "Read string:\n";
wcout << text << '\n';
wcout << wstring(dataSize/sizeof(wchar_t), L'*') << " <-- 2nd call size\n";
wcout << wstring(dataSize1/sizeof(wchar_t), L'-') << " <-- 1st call size\n";
}
操作系统:Windows 7 64 位 SP1
编辑
我偶然在示例重现代码中读到的特定注册表项似乎引起了一些混淆。
所以,让我澄清一下,我从注册表中读取该 key 只是作为一个测试。这不是生产代码,我不对那个特定的 key 感兴趣。随意向注册表添加一个简单的测试键和一些测试字符串值。
对困惑感到抱歉。
最佳答案
RegGetValue()
比 RegQueryValueEx()
更安全,因为如果字符串值还没有空终止符,它会人为地将空终止符添加到字符串值的输出中。
第一次调用返回数据大小加上额外空终止符的空间,以防实际数据尚未以空终止。我怀疑 RegGetValue()
在此阶段没有查看真实数据,它只是无条件地执行 data size + sizeof(wchar_t)
以确保安全。
(36 * sizeof(wchar_t)) + (1 * sizeof(wchar_t)) = 74
第二次调用返回读取的实际数据的实际大小。只有在必须人为添加一个时,该大小才会包括额外的空终止符。在这种情况下,您的数据在路径中有 35 个字符,并且存在一个真正的空终止符(行为良好的应用程序应该这样做),因此不需要添加额外的空终止符。
((35+1) * sizeof(wchar_t)) + (0 * sizeof(wchar_t)) = 72
现在,话虽如此,您真的不应该首先直接从注册表中读取以获取 CommonFilesDir
路径(或任何其他系统路径)。你应该使用 SHGetFolderPath(CSIDL_PROGRAM_FILES_COMMON)
或 SHGetKnownFolderPath(FOLDERID_ProgramFilesCommon)
反而。让 Shell 为您处理注册表。这在 Windows 版本中是一致的,因为注册表设置可能会从一个版本移动到另一个版本,以及考虑每个用户路径与系统全局路径。这些是首先引入 CSIDL
API 的主要原因。
关于c++ - 连续调用 RegGetValue 会为同一字符串返回两种不同的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29223180/
我正在测试这个功能::RegGetValue .下面的代码返回成功。 DWORD data_size = 0; LONG result = ::RegGetValue(HKEY_LOCAL_MACHI
我正在尝试用 C++ 编写(我认为会是)一个简单的脚本来搜索注册表(特别是 SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall)并返回 Displa
假设您要开发一个函数,给定一个有效的注册表项句柄和一个值名称,如果输入项下存在该值,则返回 true,如果不存在,则返回 false它不会,并在所有其他情况下抛出 C++ 异常。 bool RegVa
我试图了解如何在 WinApi 中使用 PVOID 数据类型,因此我尝试使用 RegGetValue 函数显示一个名为 MyValue 的值(它是一个 DWORD 值),但它对我不起作用。 这是我的代
在某些代码中,我使用了 Win32 RegGetValue()从注册表中读取字符串的 API。 我两次调用上述 API: 第一次调用的目的是获得合适的大小,以便为字符串分配目标缓冲区。 第二次调用从注
注册表函数在确实存在的键上返回“未找到”。我有正确的字符集并使用双反斜杠,所以这不是问题。 这是导出 key 的输出: [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\N
这个问题与c++有关,有多种变体,但我正在尝试在C中使用注册表函数。我知道包括,那么为什么它没有看到RegGetValue()。它是C++独有的吗?有没有办法在C中使用它? 这是我发现的一些代码,我试
Reading the Windows registry key "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" using RegGetValue()
我是一名优秀的程序员,十分优秀!