我认为在表示多字符串原始缓冲区方面,vector<wchar_t> 比 wstring 更加清楚。此外,还请注意,由于 RegGetValue API 返回的大小值以字节为单位,因此必须先将它正确转换成 wchar_t 计数,然后才能传递给 vector::resize 方法。 然后,可以第二次调用 RegGetValue API,在之前分配的缓冲区中写入实际的多字符串数据: retCode = ::RegGetValue( hKey, subKey.c_str(), value.c_str(), RRF_RT_REG_MULTI_SZ, nullptr, &data[0], &dataSize); &data[0] 自变量指向输出缓冲区的开头。 同样,必须检查 API 返回代码,并指明抛出 C++ 异常的错误条件: if(retCode != ERROR_SUCCESS){ throwRegistryError{ "Cannot read multi-string"from registry", retCode};} 最好也使用作为输出参数由 RegGetValue API 返回的 dataSize 值适当地重设数据缓冲区的大小: data.resize( dataSize / sizeof( wchar_t) ); 此时,数据变量(即 vector<wchar_t>)存储以双 NUL 结尾的字符串序列。最后一步是,解析此数据结构,并将它转换成级别更高且更便捷的 vector<wstring>: // Parse the double-NUL-terminated string into a vector<wstring>std::vector<std::wstring> result; constwchar_t* currStringPtr = &data[0]; while(*currStringPtr != L'0'){ // Current string is NUL-terminated, so get its length with wcslenconstsize_t currStringLength = wcslen(currStringPtr); // Add current string to result vectorresult.push_back(std::wstring{ currStringPtr, currStringLength }); // Move to the next stringcurrStringPtr += currStringLength + 1;} 最后,可以将结果 vector<wstring> 对象返回给调用方: returnresult; 可以按下面的方式直接调用此 RegGetMultiString C++ 包装器: vector<wstring> multiString = RegGetMultiString( HKEY_CURRENT_USER, subkey, L "MyMultiSz"); 同样,Win32 RegGetValue API 的所有复杂性是被隐藏在更高级别的便捷 C++ 接口后面了。 枚举注册表项下的值另一常见的 Windows 注册表操作是枚举给定注册表项下的值。Windows 为此提供了 RegEnumValue API (bit.ly/2jB4kaV)。在本文中,我将介绍如何使用此 API 来获取给定注册表项下值的名称和类型列表(枚举过程包装在更高级别的便捷 C++ 函数中)。自定义 C++ 函数可以将与要枚举的项相关的有效 HKEY 句柄用作输入。如果成功,此自定义 C++ 包装器函数会返回一对向量: 这对向量中的第一项是包含值名称的 wstring,第二项是表示值类型的 DWORD。所以,此 C++ 包装器函数的原型如下所示: std::vector<std::pair<std::wstring, DWORD>> RegEnumValues(HKEY hKey) 现在,我将详细介绍枚举过程。我的想法是先调用 RegQueryInfoKey (bit.ly/2jraw2H) API 来获取一些有用的枚举前信息,如给定注册表项下的值总计数和值名称最大长度,如图 1 中所示。 图 1:调用 RegQueryInfoKey API DWORD valueCount{};DWORD maxValueNameLen{};LONG retCode = ::RegQueryInfoKey( hKey, nullptr, // No user-defined classnullptr, // No user-defined class sizenullptr, // Reservednullptr, // No subkey countnullptr, // No subkey max lengthnullptr, // No subkey class length&valueCount, &maxValueNameLen, nullptr, // No max value lengthnullptr, // No security deornullptr// No last write time); 请注意,我对不关注的各条信息传递的是 nullptr。当然,必须检查返回值,并在调用上述 API 出错时抛出异常: if(retCode != ERROR_SUCCESS){ throwRegistryError{ "Cannot query key info from"the registry", retCode};} (责任编辑:本港台直播) |