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

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

时间:2017-07-11 15:22来源:本港台直播 作者:本港台直播 点击:
根据 Windows 开发人员中心 RegQueryInfoKey 函数页 ( bit.ly/2lctUDt ),针对值名称最大长度返回的大小(存储在前面代码的 maxValueNameLen 变量中)不包括终止符 NU

根据 Windows 开发人员中心 RegQueryInfoKey 函数页 (bit.ly/2lctUDt),针对值名称最大长度返回的大小(存储在前面代码的 maxValueNameLen 变量中)不包括终止符 NUL;因此,让我们来调整一下此值,即添加一个值,以在分配缓冲区来读取值名称时将终止符 NUL 考虑在内:

maxValueNameLen++;

然后,可以分配适当大小的缓冲区,在每个枚举步骤读取值名称;成本低、高效率的 std::unique_ptr<wchar_t[]> 可用于这一目的:

autonameBuffer = std::make_unique< wchar_t[]>(maxValueNameLen);

采用值名称和值类型成对形式的枚举结果可以存储在 std::vector 中:

std::vector<std::pair<std::wstring, DWORD>> values;

你在枚举过程中将内容分批添加到此向量中,然后在枚举完成时将“值”返回给调用方。

然后,可以使用 for 循环,重复调用 RegEnumValue API,并在每个循环访问步骤枚举一个新值:

for(DWORD index = 0; index < valueCount; index++){ // Call RegEnumValue to get data of current value ...}

请注意,valueCount 是通过枚举前最初的 RegQueryInfoKey 调用获取而来。

在 for 循环主体中,可以调用 RegEnumValue API 来获取当前值的相应信息。在此上下文中,关注的是值名称和值类型。值名称是从之前分配的 nameBuffer 中读取;值类型存储在简单的 DWORD 中。所以,在 for 循环主体中,可以编写如下代码:

DWORD valueNameLen = maxValueNameLen;DWORD valueType{};retCode = ::RegEnumValue( hKey, index, nameBuffer.get(), &valueNameLen, nullptr, // Reserved&valueType, nullptr, // Not interested in datanullptr// Not interested in data size

和往常一样,最好检查 API 返回值,并在出错时抛出异常:

if(retCode != ERROR_SUCCESS){ throwRegistryError{ "Cannot get value info from the registry", retCode};}

如果成功,RegEnumValue API 会在提供的 nameBuffer 中写入值名称,并在 valueType 变量中写入值类型。因此,可以使用这两条信息生成一对<wstring, DWORD>,然后将此信息对添加到枚举结果向量中:

values.push_back(std::make_pair( std::wstring{ nameBuffer.get(), valueNameLen }, valueType));

在 for 循环结束后,可以将结果“值”向量返回给调用方:

returnvalues;

然后,调用方只需按下面的方式调用 C++ 包装器函数,即可枚举注册表项下的所有值:

autovalues = RegEnumValues(hKey); // For each valuefor( constauto& v : values){ // Process v.first (value's name) and v.second (value's type)// ...}

类似的编码模式可用于枚举给定注册表项下的子项;在这种情况下,必须使用 Win32 RegEnumKeyEx (bit.ly/2k3VEX8) API,而不是前面介绍的 RegEnumValue。与本文相关联的下载内容中提供了此子项枚举函数代码。

原始 HKEY 句柄的安全资源管理器

可以安全便捷地将原始 HKEY Win32 句柄类型表示的注册表项包装在 C++ 资源管理器类中。类析构函数会对包装的原始句柄正确调用 RegCloseKey API,从而自动关闭句柄。此外,移动构造函数和移动赋值运算符等移动语义运算可以定义为在 C++ 资源管理器类的不同实例之间高效转让已包装句柄的所有权。为了提高效率,所有不会抛出异常的类方法均标记为 noexcept,以便 C++ 编译器可以生成更为优化的代码。这个便捷的项资源管理器 C++ 类 RegKey 在本文随附的 Registry.hpp 文件中实现。在这个可重用的纯标头文件中,还可以找到几个帮助程序函数的实现代码: RegOpenKey 和 RegCreateKey 分别包装 Win32 API RegOpenKeyEx 和 RegCreateKeyEx,同时返回安全包装在上述 C++ 资源管理器类中的 HKEY 句柄。如果出错,这些 C++ 函数会抛出 RegistryError 异常,同时包装原始 C 接口 Win32 API 返回的错误代码。

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