使用 C++11 range for
-loop 来枚举 Windows 注册表键/值、文件夹中的文件和 Windows Management Instrumentation (WMI) 查询,可以不需要样板初始化代码或知道底层的 Win32 API
优点
- 资源管理由 RAII 完成:句柄和资源在
Enumerator
's 的析构函数中释放。 - Windows API 使用细节是从用户那里抽象出来的。
- 要编写的样板代码更少,只需专注于您的业务逻辑。
缺点
- 生成的迭代器
Enumerator
不能在 STL 算法中使用,因为底层枚举对象不是集合。 - 这不能应用于使用EnumWindows等异步回调完成的枚举,因为回调不能重构为 range
for
循环迭代器。
枚举文件夹示例
EnumFolder
类采用原始Win32 API文件夹枚举的MSDN示例来枚举文件夹。EnumFolder
实现在后面的部分中显示。
#include "EnumFolder.h"
EnumFolder enumFolder(L"c:\\temp");
for (auto const& ffd : enumFolder)
{
if (IsFolder(ffd))
{
std::wcout << L" " << ffd.cFileName << " <DIR>\n";
}
else
{
LARGE_INTEGER filesize;
filesize.LowPart = ffd.nFileSizeLow;
filesize.HighPart = ffd.nFileSizeHigh;
std::wcout << L" " << ffd.cFileName << " "
<< filesize.QuadPart << L" bytes\n";
}
}
枚举注册表项示例
与下面这个简洁示例的原始Win32注册表枚举的MSDN示例相比,开发人员无需编写那么多行样板代码。
#include "EnumRegistryKey.h"
EnumRegistryKey enumRegistryKey(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft");
for (auto const& szKey : enumRegistryKey)
{
std::wcout << szKey << L"\n";
}
枚举注册表值示例
for
这是使用 range -loop枚举注册表值的示例。
#include "EnumRegistryValue.h"
EnumRegistryValue enumRegistryValue(HKEY_CURRENT_USER, L"Software\\7-Zip\\Compression");
for (auto const& szValueName : enumRegistryValue)
{
std::wcout << szValueName << L"\n";
}
枚举 WMI 示例
这是枚举系统中运行的进程的 WMI 查询结果的示例,其中包含 ranged for
-loop。
注意:必须为 WMI 初始化和取消初始化 COM 运行时。您可以尝试更改 SQL 查询并查看它返回的结果。
#include "EnumWmi.h"
if (!InitializeCOM())
{
std::cerr << "InitializeCOM() fails! Program exits.\n";
return 1;
}
{
EnumWmi enumWmi(L"SELECT * FROM Win32_Process");
for (const auto& process : enumWmi)
{
_bstr_t str = process[L"Name"].bstrVal;
std::cout << "Program name: " << str << std::endl;
}
}
CoUninitialize();
EnumFolder 类是如何实现的
要启用 C++11 range for
-loop,基本上需要编写两个类:Enumerator
充当'collection'类的类和iterator
迭代'collection'的类。为简单起见,EnumFolder
这里只解释类,因为其他Enumerator
涉及注册表和 WMI 的类需要深入了解它们的工作原理。
class CStringArrayIterator
{
public:
CStringArrayIterator(CStringArray& collection, INT_PTR const index):
m_index(index),
m_collection(collection)
{
}
bool operator!= (CStringArrayIterator const & other) const
{
return m_index != other.m_index;
}
CString& operator* () const
{
return m_collection[m_index];
}
CStringArrayIterator const & operator++ ()
{
++m_index;
return *this;
}
private:
INT_PTR m_index;
CStringArray& m_collection;
};
inline CStringArrayIterator begin(CStringArray& collection)
{
return CStringArrayIterator(collection, 0);
}
inline CStringArrayIterator end(CStringArray& collection)
{
return CStringArrayIterator(collection, collection.GetCount());
}