使用 CSettingsStore 枚举子项
Enumerating subkeys with CSettingsStore
我一直在考虑使用 CSettingsStore
class。
我知道如何从注册表中读取值。示例:
CSettingsStore store(TRUE, TRUE);
if (store.Open(_T("Software\TruckleSoft\VisitsRota")))
{
if (store.Read(_T("AppPath"), m_strPathVisitsRota))
{
//yes, but is the path still valid
if (!PathFileExists(m_strPathVisitsRota))
{
// it exists
m_strPathVisitsRota = _T("");
}
}
}
现在,文档中的状态是:
The security access depends on the bReadOnly
parameter. If bReadonly
is FALSE
, the security access will be set to KEY_ALL_ACCESS
. If bReadyOnly
is TRUE
, the security access will be set to a combination of KEY_QUERY_VALUE
, KEY_NOTIFY
and KEY_ENUMERATE_SUB_KEYS
.
所以这意味着你可以枚举子键。但是我找不到一个例子来解释如何使用这个 class.
来枚举一组键/值对
此答案正在进行中。
页眉
#pragma once
#include <afxsettingsstore.h>
#include <vector>
class CMySettingsStore :
public CSettingsStore
{
public:
CMySettingsStore(BOOL bAdmin, BOOL bReadOnly);
void EnumKey(std::vector<CString> &vecKeys);
};
来源
#include "pch.h"
#include "CMySettingsStore.h"
CMySettingsStore::CMySettingsStore(BOOL bAdmin, BOOL bReadOnly)
: CSettingsStore(bAdmin, bReadOnly)
{
}
void CMySettingsStore::EnumKey(std::vector<CString>& vecKeys)
{
DWORD dwIndex = 0;
long lResult = ERROR_SUCCESS;
vecKeys.clear();
while (lResult == ERROR_SUCCESS)
{
CString strSubKey;
DWORD dwLength = _MAX_PATH;
lResult = m_reg.EnumKey(dwIndex, strSubKey.GetBuffer(_MAX_PATH), &dwLength);
strSubKey.ReleaseBuffer();
dwIndex++;
vecKeys.push_back(strSubKey);
}
}
测试代码
代码假定您的对话框中有一个 CListBox
控件:
CMySettingsStore mySettings(FALSE, TRUE);
if (mySettings.Open(_T("Software\xxxx")))
{
std::vector<CString> list;
mySettings.EnumKey(list);
mySettings.Close();
for (const auto& strSubKey : list)
{
m_lbData.AddString(strSubKey);
}
}
上面的方法有效并为我提供了指定键的子键列表。但是,我还没有弄清楚如何枚举给定键中的值。
请注意,KEY_ENUMERATE_SUB_KEYS
是一个请求访问枚举子项的标志,它实际上并没有这样做。
KEY_ALL_ACCESS
是不同标志的组合,包括 KEY_ENUMERATE_SUB_KEYS
。因此在这两种情况下都需要枚举访问权限。
枚举值我们需要::RegEnumValue
API,这个方法没有包裹在CRegKey
中,不过没关系,我们可以直接得到HKEY
。
这是基于您的代码和 Microsoft sample
的示例
void CMySettingsStore::EnumKeys(std::vector<CString>& vec)
{
vec.clear();
DWORD subkey_total;
if (ERROR_SUCCESS != RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
&subkey_total, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
return;
wchar_t buf[1024];
for (DWORD i = 0; i < subkey_total; i++)
{
DWORD len = _countof(buf);
if (ERROR_SUCCESS == m_reg.EnumKey(i, buf, &len))
vec.push_back(buf);
}
}
void CMySettingsStore::EnumValues(std::vector<CString>& vec)
{
vec.clear();
DWORD values_total;
if (ERROR_SUCCESS != RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
NULL, NULL, NULL, &values_total, NULL, NULL, NULL, NULL))
return;
wchar_t buf[1024];
for (DWORD i = 0; i < values_total; i++)
{
DWORD len = _countof(buf);
if (ERROR_SUCCESS == RegEnumValue(m_reg.m_hKey, i, buf, &len,
NULL, NULL, NULL, NULL))
vec.push_back(buf);
}
}
来自问题作者的更新
此代码并未解决所有代码分析警告,但它确实添加了错误处理并支持获取值 types:
#include "stdafx.h"
#include "MySettingsStore.h"
CMySettingsStore::CMySettingsStore(BOOL bAdmin, BOOL bReadOnly)
: CSettingsStore(bAdmin, bReadOnly)
{
}
bool CMySettingsStore::EnumKeys(std::vector<CString>& vec)
{
vec.clear();
DWORD subkey_total{}, lResult{};
if (RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
&subkey_total, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
wchar_t buf[1024];
for (DWORD i = 0; i < subkey_total; i++)
{
DWORD len = _countof(buf);
lResult = m_reg.EnumKey(i, buf, &len);
if(lResult == ERROR_SUCCESS || ERROR_NO_MORE_ITEMS)
vec.push_back(buf);
}
if (lResult != ERROR_NO_MORE_ITEMS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
return true;
}
bool CMySettingsStore::EnumValues(std::map<CString, DWORD>& map)
{
map.clear();
DWORD values_total{}, dwType{}, lResult{};
if (RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
NULL, NULL, NULL, &values_total, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
wchar_t buf[1024];
for (DWORD i = 0; i < values_total; i++)
{
DWORD len = _countof(buf);
lResult = RegEnumValue(m_reg.m_hKey, i, buf, &len,
NULL, &dwType, NULL, NULL);
if(lResult == ERROR_SUCCESS || lResult == ERROR_NO_MORE_ITEMS)
map.emplace(buf, dwType);
}
if (lResult != ERROR_NO_MORE_ITEMS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
return true;
}
CString CMySettingsStore::GetLastErrorAsString(DWORD dwError)
{
LPVOID lpMsgBuf{};
CString strError;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf,
0,
nullptr);
strError = static_cast<LPTSTR>(lpMsgBuf);
LocalFree(lpMsgBuf);
return strError;
}
我一直在考虑使用 CSettingsStore
class。
我知道如何从注册表中读取值。示例:
CSettingsStore store(TRUE, TRUE);
if (store.Open(_T("Software\TruckleSoft\VisitsRota")))
{
if (store.Read(_T("AppPath"), m_strPathVisitsRota))
{
//yes, but is the path still valid
if (!PathFileExists(m_strPathVisitsRota))
{
// it exists
m_strPathVisitsRota = _T("");
}
}
}
现在,文档中的状态是:
The security access depends on the
bReadOnly
parameter. IfbReadonly
isFALSE
, the security access will be set toKEY_ALL_ACCESS
. IfbReadyOnly
isTRUE
, the security access will be set to a combination ofKEY_QUERY_VALUE
,KEY_NOTIFY
andKEY_ENUMERATE_SUB_KEYS
.
所以这意味着你可以枚举子键。但是我找不到一个例子来解释如何使用这个 class.
来枚举一组键/值对此答案正在进行中。
页眉
#pragma once
#include <afxsettingsstore.h>
#include <vector>
class CMySettingsStore :
public CSettingsStore
{
public:
CMySettingsStore(BOOL bAdmin, BOOL bReadOnly);
void EnumKey(std::vector<CString> &vecKeys);
};
来源
#include "pch.h"
#include "CMySettingsStore.h"
CMySettingsStore::CMySettingsStore(BOOL bAdmin, BOOL bReadOnly)
: CSettingsStore(bAdmin, bReadOnly)
{
}
void CMySettingsStore::EnumKey(std::vector<CString>& vecKeys)
{
DWORD dwIndex = 0;
long lResult = ERROR_SUCCESS;
vecKeys.clear();
while (lResult == ERROR_SUCCESS)
{
CString strSubKey;
DWORD dwLength = _MAX_PATH;
lResult = m_reg.EnumKey(dwIndex, strSubKey.GetBuffer(_MAX_PATH), &dwLength);
strSubKey.ReleaseBuffer();
dwIndex++;
vecKeys.push_back(strSubKey);
}
}
测试代码
代码假定您的对话框中有一个 CListBox
控件:
CMySettingsStore mySettings(FALSE, TRUE);
if (mySettings.Open(_T("Software\xxxx")))
{
std::vector<CString> list;
mySettings.EnumKey(list);
mySettings.Close();
for (const auto& strSubKey : list)
{
m_lbData.AddString(strSubKey);
}
}
上面的方法有效并为我提供了指定键的子键列表。但是,我还没有弄清楚如何枚举给定键中的值。
请注意,KEY_ENUMERATE_SUB_KEYS
是一个请求访问枚举子项的标志,它实际上并没有这样做。
KEY_ALL_ACCESS
是不同标志的组合,包括 KEY_ENUMERATE_SUB_KEYS
。因此在这两种情况下都需要枚举访问权限。
枚举值我们需要::RegEnumValue
API,这个方法没有包裹在CRegKey
中,不过没关系,我们可以直接得到HKEY
。
这是基于您的代码和 Microsoft sample
的示例void CMySettingsStore::EnumKeys(std::vector<CString>& vec)
{
vec.clear();
DWORD subkey_total;
if (ERROR_SUCCESS != RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
&subkey_total, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
return;
wchar_t buf[1024];
for (DWORD i = 0; i < subkey_total; i++)
{
DWORD len = _countof(buf);
if (ERROR_SUCCESS == m_reg.EnumKey(i, buf, &len))
vec.push_back(buf);
}
}
void CMySettingsStore::EnumValues(std::vector<CString>& vec)
{
vec.clear();
DWORD values_total;
if (ERROR_SUCCESS != RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
NULL, NULL, NULL, &values_total, NULL, NULL, NULL, NULL))
return;
wchar_t buf[1024];
for (DWORD i = 0; i < values_total; i++)
{
DWORD len = _countof(buf);
if (ERROR_SUCCESS == RegEnumValue(m_reg.m_hKey, i, buf, &len,
NULL, NULL, NULL, NULL))
vec.push_back(buf);
}
}
来自问题作者的更新
此代码并未解决所有代码分析警告,但它确实添加了错误处理并支持获取值 types:
#include "stdafx.h"
#include "MySettingsStore.h"
CMySettingsStore::CMySettingsStore(BOOL bAdmin, BOOL bReadOnly)
: CSettingsStore(bAdmin, bReadOnly)
{
}
bool CMySettingsStore::EnumKeys(std::vector<CString>& vec)
{
vec.clear();
DWORD subkey_total{}, lResult{};
if (RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
&subkey_total, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
wchar_t buf[1024];
for (DWORD i = 0; i < subkey_total; i++)
{
DWORD len = _countof(buf);
lResult = m_reg.EnumKey(i, buf, &len);
if(lResult == ERROR_SUCCESS || ERROR_NO_MORE_ITEMS)
vec.push_back(buf);
}
if (lResult != ERROR_NO_MORE_ITEMS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
return true;
}
bool CMySettingsStore::EnumValues(std::map<CString, DWORD>& map)
{
map.clear();
DWORD values_total{}, dwType{}, lResult{};
if (RegQueryInfoKey(m_reg.m_hKey, NULL, NULL, NULL,
NULL, NULL, NULL, &values_total, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
wchar_t buf[1024];
for (DWORD i = 0; i < values_total; i++)
{
DWORD len = _countof(buf);
lResult = RegEnumValue(m_reg.m_hKey, i, buf, &len,
NULL, &dwType, NULL, NULL);
if(lResult == ERROR_SUCCESS || lResult == ERROR_NO_MORE_ITEMS)
map.emplace(buf, dwType);
}
if (lResult != ERROR_NO_MORE_ITEMS)
{
const DWORD dwError = ::GetLastError();
AfxMessageBox(GetLastErrorAsString(dwError), MB_OK | MB_ICONWARNING);
return false;
}
return true;
}
CString CMySettingsStore::GetLastErrorAsString(DWORD dwError)
{
LPVOID lpMsgBuf{};
CString strError;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf,
0,
nullptr);
strError = static_cast<LPTSTR>(lpMsgBuf);
LocalFree(lpMsgBuf);
return strError;
}