Search code examples
c++pythonregistry

c++ loop through registry recursively is slow


Have an annoying problem with my code, probably I am doing something wrong because my Python implementation is much faster!

C++ implementation problems:

  1. Iterating over "HKEY_CLASSES_ROOT" takes a lot of ram, I assume it's because c++ implementation uses lots of variables. Fixed
  2. It's also slow, much slower than python implantation of the code Fixed
  3. The code even slower when trying to iterate over HKEY_CLASSES_ROOT Fixed

New Questions:

  1. Thanks to Nam Nguyen i understood what causing the leaks in my code, and directly effecting execution time, the code below is the fixed one. how come c++ implementation runs as fast as my python implementation?

C++ implementation:

#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string>

using namespace std;

#define MAX_KEY_LENGTH 255

int RecurseOpenRegEx(HKEY hkey, string subKey = "",string search = "nothing", DWORD sum = 0)
{
   TCHAR csubKey[MAX_KEY_LENGTH];
   DWORD nSubKeys = 0;
   DWORD pathLength = MAX_PATH;
   TCHAR storeKeyName[MAX_KEY_LENGTH];
   DWORD keyLength;
   HKEY hKey = hkey; //somehow i need to reassign HKEY, otherwise it won't pass it with the function, this is bigger than me tough...

   const char * ccsearch = search.c_str();
   const char * ccsubKey;


   if (subKey != "")
   {
       ccsubKey = subKey.c_str();
       copy(subKey.begin(), subKey.end(),csubKey); //convert string to TCHAR
   }

   if (RegOpenKeyEx(hkey, ccsubKey, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
   {
       if (RegQueryInfoKey(hkey, csubKey, &pathLength, NULL,&nSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
       {
           sum += nSubKeys;
           for (DWORD subKeyIndex = 0; subKeyIndex < nSubKeys; subKeyIndex++)
           {
               keyLength = MAX_KEY_LENGTH;
               if (RegEnumKeyEx(hkey, subKeyIndex, storeKeyName, &keyLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
               {
                   string sKeyName = storeKeyName; //Convert TCHAR to string explicitly


                   if (subKey != "")
                   {
                       sKeyName = subKey + "\\" + sKeyName;
                   }
                   sum += RecurseOpenRegEx(hKey, sKeyName);
               }
           }
       }
   }
   RegCloseKey(hkey); //Now closing the right key
   return sum;
}

int main()
{
   cout << "sum of all keys: " << RecurseOpenRegEx(HKEY_LOCAL_MACHINE);
   return 0;
}

Python implementation:

import winreg

def recurseRegistrySearch(key, keySearch = "",subkey = "", subkeypath = "", x = 0):
    key = winreg.OpenKey(key, subkey, 0)
    y = winreg.QueryInfoKey(key)[0]
    x += y
    for items in range(x):
        try:
            subkey = winreg.EnumKey(key, items)
            if ((keySearch.lower() in subkey.lower()) and (keySearch != "")):
                print(subkeypath + "\\" + subkey)
            x += recurseRegistrySearch(key, keySearch, subkey, subkeypath = subkeypath + "\\" + subkey)
        except WindowsError:
            pass
    return x

print("sum of all keys: {0}".format(recurseRegistrySearch(winreg.HKEY_CLASSES_ROOT)))

Solution

  • There is leak of resource in your code. You open hkey but you close hKey (note the difference in case of k and K).

    On a side note, you store the opened registry key into hkey itself. And it happens that hkey is the passed in parameter, shared among all calls to RecurseOpenRegEx. That is why "somehow i need to reassign HKEY".

    Basically, what I can advise you now is immediately clean up your code. Bugs like these are hard to spot when your code is a too difficult to read. Once done, I believe you will find it easier to debug/trace.