foobar
foobar

Reputation: 2943

Most Efficient way to enumerate all registry keys

I am using following function to enumerate all registry keys for a particular key and subkey in a vector and return it.

But this code seems to run very slow for large Key Values, like for above 200000+ keys, it takes more than 5 minutes to complete. Just want to know how can I make it more efficient.

vector<string> CRegistryAPI::EnumKeys(HKEY RootKey, string SubKey)
{
    DWORD keyLen = 255;
    int index = 0;
    int ret = 0;
    PFILETIME lastWrite = 0;
    HKEY hKey = 0;
    char keyName[255];
    vector<string> keyList;

    if (RegOpenKeyExA(RootKey, SubKey.c_str(), 0, KEY_ENUMERATE_SUB_KEYS,&hKey) != ERROR_SUCCESS)
        return keyList;
    do
    {
        ret = RegEnumKeyExA(hKey, index, keyName, &keyLen, 0, 0, 0, lastWrite);
        if (ret == ERROR_SUCCESS)
        {
            keyList.push_back(keyName);
        }
        index ++;
        keyLen = 255; 
    }
    while (ret == ERROR_SUCCESS);

    if (hKey != NULL)
        RegCloseKey(hKey);

    return keyList;
}

Any help is appreciated. Thanks.

Upvotes: 0

Views: 628

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595762

One optimization you can do is use RegQueryInfoKey() to query information about a given key before then enumerating its contents. For instance, you can preallocate your vector's capacity so it does not have to be reallocated multiple times during the enumeration:

RegQueryInfoKey(hKey, 0, 0, 0, 0, 0, 0, &dwNumValues, 0, 0, 0, 0);
keyList.reserve(keyList.size()+dwNumValues);

Also, your enumeration is not ensuring your buffer is null-terminated when pushing it into the vector. Even if it were, your way of pushing currently requires std::string to calculate the buffer length each time. You should instead use the buffer length that is returned to you:

keyList.push_back(string(keyName, keyLen));

Upvotes: 1

Related Questions