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

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

时间:2017-07-11 15:22来源:本港台直播 作者:本港台直播 点击:
现在,让我们深入探究实现代码。如前所述,在此示例中,RegGetValue 的调用模式相当简单。只需声明一个 DWORD 变量,用于存储从注册表中读取的值: DWO

现在,让我们深入探究实现代码。如前所述,在此示例中,RegGetValue 的调用模式相当简单。只需声明一个 DWORD 变量,用于存储从注册表中读取的值:

DWORD data{};

然后,需要声明另一个 DWORD 变量,用于表示 RegGetValue 写入的输出缓冲区的大小(以字节为单位)。请注意,这个简单示例中的输出缓冲区就是以前的“数据”变量,它的大小始终是 DWORD 的大小:

DWORD dataSize = sizeof(data);

不过,请注意,不能将 dataSize 标记为常量,因为它是 RegGetValue 的输入和输出参数。

然后,可以调用 RegGetValue API:

LONG retCode = ::RegGetValue( hKey, subKey.c_str(), value.c_str(), RRF_RT_REG_DWORD, nullptr, &data, &dataSize);

输入 wstring 对象通过 wstring::c_str 方法转换成原始 C 样式字符串指针。RRF_RT_REG_DWORD 标志将注册表值的类型限制为 DWORD。如果要读取的注册表值为不同类型,那么出于稳妥考虑 RegGetValue 函数调用会失败。

最后两个参数表示输出缓冲区的地址(在此示例中,为数据变量的地址)和用于存储输出缓冲区大小的变量的地址。实际上,在返回时,RegGetValue 会报告写入输出缓冲区的数据的大小。在读取简单 DWORD 值的示例中,数据大小始终为 4 字节,即 sizeof(DWORD)。然而,此大小参数对大小可变的值(如字符串)更为重要;我将在本文后面对此进行介绍。

调用 RegGetValue 函数后,可以检查返回代码,并在出错时抛出异常:

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

请注意,RegGetValue 返回的错误代码 (retCode) 已嵌入异常对象中,稍后可由处理异常的代码进行检索。

相反,如果成功,DWORD 数据变量可以直接返回给调用方:

returndata;

以上便是对函数实现代码的介绍。

调用方可以使用下面的代码直接调用此 C++ 包装器函数:

DWORD data = RegGetDword(HKEY_CURRENT_USER, subkey, L "MyDwordValue");

请注意,与原始 RegGetValue C API 调用相比,此代码非常简单。只需将句柄传递给打开的注册表项(在此示例中,为 HKEY_CURRENT_USER 预定义项),即包含子项和值名称的字符串。如果成功,DWORD 值会返回给调用方。然而,如果出错,则会抛出 RegistryError 类型的自定义异常。与调用 RegGetValue 相比,这种代码不仅级别更高,而且要简单得多。实际上,RegGetValue的复杂性是被隐藏在这个自定义 RegGetDword C++ 包装器函数中了。

可以通过同样的方式从注册表中读取 QWORD(64 位数据)值;在这种情况下,只需将注册表值的 DWORD 类型替换为 64 位 ULONGLONG。

读取注册表中的字符串值

读取注册表中的 DWORD 值相当简单:只需调用一次 RegGetValue Win32 API 就已足够。这主要是因为 DWORD 值的大小不变,DWORD 的大小始终为 4 字节。相比之下,读取注册表中的字符串又加了一层复杂性,因为字符串是大小可变的数据。在这种情况下,我的想法是调用 RegGetValue API 两次: 在第一次调用中,请求此 API 返回输出字符串缓冲区的相应大小。接下来,动态分配适当大小的缓冲区。最后,第二次调用 RegGetValue,将字符串数据写入之前分配的缓冲区中。(我在之前的文章“在 Win32 API 边界使用 STL 字符串”(msdn.com/magazine/mt238407) 中详细介绍过这种模式)。

首先,让我们来看看 C++ 更高级别包装器函数的原型:

std::wstring RegGetString( HKEY hKey, conststd::wstring& subKey, conststd::wstring& value)

与 DWORD 示例一样,这相对于原始复杂的 RegGetValue C API 原型更为简单。字符串值以 std::wstring 实例的形式从函数返回。反之,如果出错,则会抛出异常。子项名称和值名称同样作为输入wstring 常量引用参数传递。

现在,我将介绍实现代码。

如前所述,我的想法是先调用 RegGetValue API,获取用于存储字符串值的输出缓冲区的大小:

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

可以看到与上面的 DWORD 值示例类似的调用语法。wstring 对象通过 wstring::c_str 方法调用转换成 C 样式字符串指针。此示例中的 RRF_RT_REG_SZ 标志将有效注册表类型限制为字符串类型 (REG_SZ)。如果成功,RegGetValue API 会在 dataSize 变量中写入相应的输出缓冲区大小(以字节为单位)。

如果失败,则需要抛出自定义 RegistryError 类的异常:

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

至此,你已了解相应的输出缓冲区大小,现在可以为输出字符串分配所需大小的 wstring 对象:

std::wstring data;data.resize(dataSize / sizeof( wchar_t));

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