本港台开奖现场直播 j2开奖直播报码现场
当前位置: 新闻频道 > IT新闻 >

码报:使用新式 C++ 访问 Windows 注册表(3)

时间:2017-07-11 15:22来源:本港台直播 作者:本港台直播 点击:
请注意,虽然 RegGetValue 返回的 dataSize 值以字节为单位,但 wstring::resize 方法应使用以 wchar_t 计数为单位的大小值。因此,必须从字节扩展为 wchar_t,用原字

请注意,虽然 RegGetValue 返回的 dataSize 值以字节为单位,但 wstring::resize 方法应使用以 wchar_t 计数为单位的大小值。因此,必须从字节扩展为 wchar_t,用原字节大小值除以 sizeof(wchar_t)。

至此,你已经有分配了足够空间的字符串,可以将指向内部缓冲区的指针传递给 RegGetValue API,这一次将在所提供的缓冲区中写入实际的字符串数据:

retCode = ::RegGetValue( hKey, subKey.c_str(), value.c_str(), RRF_RT_REG_SZ, nullptr, &data[0], &dataSize);

&data[0] 是 wstring 内部缓冲区的地址,将由 RegGetValue API 写入。

和往常一样,请务必验证 API 调用的结果,并在出错时抛出异常:

if(retCode != ERROR_SUCCESS){ throwRegistryError{ "Cannot read string from registry", retCode};}

请注意,如果成功,RegGetValue 会在 dataSize 变量中写入实际结果字符串大小(以字节为单位)。必须根据此大小重设 wstring 对象的大小。由于 dataSize 是以字节为单位,开奖,因此在处理 wstring 时最好转换成相应的 wchar_t 计数:

DWORD stringLengthInWchars = dataSize / sizeof( wchar_t);

此外,dataSize 包括输出字符串的终止符 NUL。不过,由于 wstring 对象已经以 NUL ­结尾,因此必须注意避免读取字符串出现虚假的双 NUL 终止符。必须删除 RegGetValue 写入的 NUL 终止符:

stringLengthInWchars--; // Exclude the NUL written by the Win32 APIdata.resize(stringLengthInWchars);

请注意,如果成功,RegGetValue API 会保证字符串以 NUL 结尾,即使注册表中存储的原始字符串不以 NUL 结尾,也不例外。这是比旧的 RegQueryValueEx API 更为安全的行为,旧 API 不保证返回的字符串以 NUL 结尾。因此,调用方必须编写其他代码来妥善处理此情况,这就增加了代码的整体复杂性和出错概率。

至此,数据变量包含从注册表中读取的字符串值,可以在函数退出之前将它返回给调用方:

returndata;

在 RegGetValue 低级别 C API 基础之上生成此便捷 RegGetString C++ 包装器后,可以按以下方式进行调用:

wstring s = RegGetString(HKEY_CURRENT_USER, subkey, L "MyStringValue");

与 DWORD 示例一样,你已在 RegGetValue Win32 API 基础之上提升了抽象级别,提供了易于使用且难以滥用的 C++ 包装器函数,以便于读取注册表中的字符串值。处理 RegGetValue API 涉及的所有细节和复杂性都安全地隐藏在这一自定义 RegGetString C++ 函数的主体中。

读取注册表中的多字符串值

另一种类型的注册表值就是所谓的“多字符串”: 一般来说,这是一组用一个注册表值打包的以双 NUL 结尾的字符串。这种以双 NUL 结尾的字符串数据结构由一系列以 NUL 结尾的 C 样式字符串组成,这些字符串占据相邻内存位置。此序列的末尾还标记有一个 NUL 终止符,因此整个结构是以两个 NUL 结尾。有关此数据结构的更多详细信息,请参阅博文“什么是以双 Null 结尾的字符串格式(不含字符串)?”(bit.ly/2jCqg2u)。

此示例中的 RegGetValue Win32 API 使用模式与前面的单字符串示例非常相似。也就是说,先调用 RegGetValue API 获取包含相应数据(在此示例中,是以双 NUL 结尾的相邻字符串的整个序列)的整个目标缓冲区的大小。然后,动态分配此类大小的缓冲区。最后,第二次调用 RegGetValue 函数,传递之前分配的缓冲区的地址,以便 API 可以在相应缓冲区中写入实际的多字符串数据。

在此示例中,必须注意存储以双 NUL 结尾的字符串的数据结构。实际上,虽然 std::wstring 可以妥善包含嵌入的 NUL(可用于存储以双 NUL 结尾的字符串结构),但我希望提升抽象级别,将以双 NUL 结尾的字符串解析成级别更高且更便捷的 vector<wstring>。

所以,读取注册表中多字符串值的 C++ 包装器函数的原型如下所示:

std::vector<std::wstring> RegGetMultiString( HKEY hKey, conststd::wstring& subKey, conststd::wstring& value)

如果成功,多字符串会以理想的 vector<wstring> 形式返回给调用方。然而,j2直播,如果出错,则会抛出常规 RegistryError 形式的异常。

在 C++ 包装器函数主体中,先调用 RegGetValue API,获取用于存储多字符串的相应输出缓冲区的大小:

DWORD dataSize{};LONG retCode = ::RegGetValue( hKey, subKey.c_str(), value.c_str(), RRF_RT_REG_MULTI_SZ, nullptr, nullptr, &dataSize);

请注意,这一次使用 RRF_RT_REG_MULTI_SZ 标志来指定多字符串注册表值类型。

和往常一样,如果出错,则会抛出异常(错误代码已嵌入 RegistryError 对象中):

if(retCode != ERROR_SUCCESS){ throwRegistryError{ "Cannot read multi-string from registry", retCode};}

如果成功,则分配适当大小的缓冲区来存储整个多字符串:

std::vector< wchar_t> data;data.resize(dataSize / sizeof( wchar_t));

(责任编辑:本港台直播)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
栏目列表
推荐内容