背景
在 Windows 上面,我们常用注册表作为一个 cache 来保存一些数据,这样当程序下一次启动的时候,读取注册表,就能获取到上一次缓存的结果
函数介绍
创建指定的注册表项
具体函数
WINADVAPI LSTATUS APIENTRY RegCreateKeyA (
_In_ HKEY hKey,
_In_opt_ LPCSTR lpSubKey,
_Out_ PHKEY phkResult
);
参数介绍
hKey:打开的注册表项的句柄,一般为 HKEY_CURRENT_USER
lpSubKey:此函数打开或创建的密钥的名称
phkResult:指向接收打开或创建的键的句柄的变量的指针
使用方法
const char* sub_key = "Software\\demo_cache";
HKEY hkey = nullptr;
LSTATUS res = ::RegCreateKeyA(HKEY_CURRENT_USER, sub_key, &hkey);
打开指定的注册表项
具体函数
WINADVAPI LSTATUS APIENTRY RegOpenKeyExA(
_In_ HKEY hKey,
_In_opt_ LPCSTR lpSubKey,
_In_opt_ DWORD ulOptions,
_In_ REGSAM samDesired,
_Out_ PHKEY phkResult
);
这里有两个参数和上面不一样,samDesired 表示要进行什么操作,如果是读操作使用 KEY_READ,写操作使用 KEY_WRITE
写入数据
具体函数
LSTATUS RegSetValueExA(
HKEY hKey,
LPCSTR lpValueName,
DWORD Reserved,
DWORD dwType,
const BYTE *lpData,
DWORD cbData
);
参数介绍
hKey:open 时所用到的 HKEY
lpValueName:相当于 key-value 里面的 key
Reserved:保留值,必须强制为0
dwType:被存储数据的类型,如果是字符串使用 REG_SZ
lpData:要存储的数据
cbData:存储数据的长度
读取数据
LSTATUS RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
读取数据的时候要调用两遍这个函数
第一遍查询数据的长度,将 lpData 设置为 null,然后返回 lpcbData 就是数据的长度
第二遍查询数据,这个时候需要分配好空间,然后查询数据
关闭指定的注册表
LSTATUS RegCloseKey(
HKEY hKey
);
hkey 是 open 的时候的 hkey
具体代码
#include <Windows.h>
#include <atlbase.h>
#include <iostream>
#include <string>
#include <vector>
const char* sub_key = "Software\\demo_cache";
bool SetValue(const std::string& key, const std::string& value) {
HKEY hkey = nullptr;
LSTATUS res = ::RegOpenKeyExA(HKEY_CURRENT_USER, sub_key, 0, KEY_WRITE, &hkey);
if (res != ERROR_SUCCESS) {
res = ::RegCreateKeyA(HKEY_CURRENT_USER, sub_key, &hkey);
}
if (res != ERROR_SUCCESS) {
return false;
}
std::shared_ptr<void> close_key(nullptr, [&](void*) {
if (hkey != nullptr) {
::RegCloseKey(hkey);
hkey = nullptr;
}
});
res = ::RegSetValueExA(hkey, key.c_str(), 0, REG_SZ, (BYTE*)value.c_str(), value.length());
if (res != ERROR_SUCCESS) {
return false;
}
return true;
}
std::string GetValue(const std::string& key) {
HKEY hkey = nullptr;
LSTATUS res = ::RegOpenKeyExA(HKEY_CURRENT_USER, sub_key, 0, KEY_READ, &hkey);
if (res != ERROR_SUCCESS) {
return "";
}
std::shared_ptr<void> close_key(nullptr, [&](void*) {
if (hkey != nullptr) {
::RegCloseKey(hkey);
hkey = nullptr;
}
});
DWORD type = REG_SZ;
DWORD size = 0;
res = ::RegQueryValueExA(hkey, key.c_str(), 0, &type, nullptr, &size);
if (res != ERROR_SUCCESS || size <= 0) {
return "";
}
std::vector<BYTE> value_data(size);
res = ::RegQueryValueExA(hkey, key.c_str(), 0, &type, value_data.data(), &size);
if (res != ERROR_SUCCESS) {
return "";
}
return std::string(value_data.begin(), value_data.end());
}
int main(void) {
bool ret = SetValue("name", "Tom");
if (ret) {
std::cout << GetValue("name") << std::endl;
}
else {
std::cout << "set value failed" << std::endl;
}
getchar();
return 0;
}
程序输出
Tom