Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Registry cleaner

  1. #1
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default Registry cleaner

    I'm trying to work on a program that cleans the registry (similar to that of ccleaner).

    My questions is (for obvious reasons, I don't want to **** up my system, so I just want to ensure I'm doing this correctly.

    Would I use RegOpenKeyEx() & RegQueryValueEx() and then check if it != ERROR_SUCCESS
    If it == ERROR_SUCCESS means the key is alright, otherwise I would use RegDeleteKey() or should I use RegDeleteValue?

    Or is there a better\safer way to perform this kind of function. I want it to be as effective as ccleaner if possible.

    Thanks!

  2. #2

    Default

    Both RegOpenKeyEx and RegQueryValueEx return an error code so to be safe both should return ERROR_SUCESS.
    Whether you need RegDeleteKey or RegDeleteValue really depends on the situation. In the case of the famous "Run" entries, you'll use RegDeleteValue as you don't want to remove the entire "Run" key.
    The last bits of programming with the registry was with C++ which worked fine for me. The only way I could find to query/modify the registry with C++ was with the functions you named.
    =|UWS|=|SA|Vince - Head Serveradmin - mohaa.uwsclan.us (MOH:AA - FT)

  3. #3
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Thanks for the info. I'll post some code later today. My next question is since I want to clean the entire registry as opposed to defining a specific key\value how would I cycle through the entire registry HIVE? Would the values for those parameters just be NULL? I have to look into this more.

  4. #4

    Default

    If you'd like to enumerate all the keys under for instance HKEY_LOCAL_MACHINE, you can use RegEnumKeyEx to fetch all the subkeys (one at a time that is) and RegEnumValue to get all the values from a subkey that is of interest to you.
    I'm curious as to how you're going to do this as at some point you'll have grab specific subkeys and with (for example) "Run" you can't just grab every "Run" key you fetch as some are used by software to store other "stuff".
    =|UWS|=|SA|Vince - Head Serveradmin - mohaa.uwsclan.us (MOH:AA - FT)

  5. #5
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    registry hives aren't locked are they? As long as you use Access all Keys then you should be fine. The only other thing is running it under an admin account. I'm not entirely sure what you mean. I guess I'm missing the point of how a regcleaner works, but I was under the impression that it returns ERROR_SUCCESS under 1 of 2 conditions.
    1. The value is empty\null
    2. If the value is referring to a path, validate the path to ensure it is actually pointing to a valid location

    If either or both of those are true then the key\value will be deleted.

    Also though, I had a second thought about this because typically RegOpenKeyEx would be needed if you're specifying a specific location in the registry hive. Since my idea is to scan the entire registry hive then theoretically I would only use RegQueryValueEx() or am I off?

    Anywho, I wouldn't be doing anything aside from checking the consistency of the value and\or key to make sure the above 2 conditions aren't causing system instability in any way.

    EDIT:
    I was going to use a switch and cases to go through the 5 root hives, unless there is a better way?

  6. #6

    Default

    Some bits of the registry are locked or readonly, don't recall which keys but it's not a whole lot that's locked. Plus you'd be able to figure that out via RegOpenKeyEx anyway as it would return an error.

    I do get what you're trying to do now. It will certainly clean out some registry keys (if empty) and values (if the path is invalid).
    But there is more to registry cleaning than that. Take the good old CCleaner for instance, it will also find extensions that are no longer in use. Not entirely sure how it does it, but I think it checks whether HKCU\Software\Microsoft\...\FileExts\* stuff is also under HKCR somewhere. My point is that a lot of the registry cleaning CCleaner does isn't as simple as checking a path

    You would use RegEnumKeyEx() to fetch all subkeys of a hive (HKLM for example).
    And then run through all those keys and use RegEnumKeyEx to get their subkeys and RegEnumValue to get their values.
    For example, you could use RegEnumKeyEx() on HKLM (HKEY_LOCAL_MACHINE) and after a couple calls you'll get a key named "Software". On Software you can call RegEnumKeyEx() again and you'll probably get "2015". On which you could call RegEnumKeyEx again to find MOHAA and then call RegEnumValue to find a value called "basepath". You could then check whether the data of basepath is still a valid path.

    As for running through the Hives, I'd say you could use an array and a for loop?
    An array of hkey's that is. Don't have a better approach right now but I will give it some thought.
    =|UWS|=|SA|Vince - Head Serveradmin - mohaa.uwsclan.us (MOH:AA - FT)

  7. #7
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Wow, wargamer, you've really showed me alot of insight in this. Thank you so much! If you're so handy in programming I'm surprised I don't see you releasing some things. I hope you don't take offense to that, because you really seem like you enjoy this sort of thing!

    Anywho, thanks again!

  8. #8
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Here is my current source

    PHP Code:
    void QueryKey(HWND hTest)

        
    HKEY     hKey;
        
    TCHAR    achKey[MAX_KEY_LENGTH];    // buffer for subkey name
        
    TCHAR     achValue[MAX_VALUE_NAME]; 
        
    DWORD     cchValue MAX_VALUE_NAME
        
    DWORD     i
        
    DWORD     retCode
        
    DWORD    cbName;            // size of name string 
        
    TCHAR    achClass[MAX_PATH] = TEXT(""); // buffer for class name 
        
    DWORD    cchClassName MAX_PATH;    // size of class string 
        
    DWORD    cSubKeys=0;            // number of subkeys 
        
    DWORD    cbMaxSubKey;            // longest subkey size 
        
    DWORD    cchMaxClass;            // longest class string 
        
    DWORD    cValues;            // number of values for key 
        
    DWORD    cchMaxValue;            // longest value name 
        
    DWORD    cbMaxValueData;        // longest value data 
        
    DWORD    cbSecurityDescriptor;        // size of security descriptor 
        
    FILETIME ftLastWriteTime;        // last write time 
        
    char     szBuff1[MAX_KEY_LENGTH];

        
    RegOpenKeyEx(HKEY_LOCAL_MACHINE00KEY_READ, &hKey);
     
        
    // Get the class name and the value count. 
        
    retCode RegQueryInfoKey(hKeyachClass, &cchClassNameNULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, &cValues, &cchMaxValue, &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);
     
        
    // Enumerate the subkeys, until RegEnumKeyEx fails.
        
    if (cSubKeys)
        {
            
    //printf( "\nNumber of subkeys: %d\n", cSubKeys);
            
    _stprintf_s(szBuff1"\nNumber of subkeys: %d\n"cSubKeys);
            
    SetWindowText(hTestszBuff1);

            for (
    i=0i<cSubKeysi++) 
            { 
                
    cbName MAX_KEY_LENGTH;
                
    retCode RegEnumKeyEx(hKeyiachKey, &cbNameNULLNULLNULL, &ftLastWriteTime); 

                for (
    i=0retCode ERROR_SUCCESSi<cValuesi++) 
                { 
                    
    cchValue MAX_VALUE_NAME
                    
    achValue[0] = '\0'
                    
    retCode RegEnumValue(hKeyiachValue, &cchValueNULLNULLNULLNULL);
             
                    if (
    retCode == ERROR_SUCCESS 
                    { 
                        
    //_tprintf(TEXT("(%d) %s\n"), i+1, achValue); 
                        
    _stprintf_s(szBuff1TEXT("(%d) %s\n"), i+1achValue);
                        
    SetWindowText(hTestszBuff1);
                    } 
                }
            }
        } 


  9. #9

    Default

    Quote Originally Posted by James View Post
    Wow, wargamer, you've really showed me alot of insight in this. Thank you so much! If you're so handy in programming I'm surprised I don't see you releasing some things. I hope you don't take offense to that, because you really seem like you enjoy this sort of thing!

    Anywho, thanks again!
    You are very welcome and yes I do enjoy programming which is why I'm currently studying it
    And no offense taken but I've been busy writing other stuff like plugins for Minecraft >.<

    As for the source code you posted...

    Quote Originally Posted by James View Post
    for (i=0, retCode = ERROR_SUCCESS; i<cValues; i++)
    You're reusing a for loop counter there which means you keep on resetting the first for loop's counter.
    And you're initialising retCode which doesn't make sense to me. It would probably be more useful to check whether it's still ERROR_SUCCESS.
    So:
    PHP Code:
    for (j=0retCode == ERROR_SUCCESS && j<cValuesj++) 
    Quote Originally Posted by James View Post
    retCode = RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL);
    This will query the values for the currently openened key that's stored in hKey.
    Problem is that, that key will always be a HKEY_LOCAL_MACHINE which has no values, only subkeys.
    You should probably use another HKEY to store subkeys in.
    For instance:
    PHP Code:
    cbName MAX_KEY_LENGTH;
    retCode RegEnumKeyEx(hKeyiachKey, &cbNameNULLNULLNULL, &ftLastWriteTime); 
    RegOpenKeyEx(HKEY_LOCAL_MACHINEachKeyNULLKEY_READ, &hSubKey); 
    Which will query HKEY_LOCAL_MACHINE for a subkey, open that subkey and store it in an HKEY called hSubKey.
    And after that you can query that subkey for values:
    PHP Code:
    retCode RegEnumValue(hSubKeykachValue, &cchValueNULLNULLNULLNULL); 
    And given your idea of cleaning the entire registry; all of that will have to loop in an elegant way.
    Could be recursive, but the amount of calls might grow too large.
    Best is probably looping like you're already doing but somehow build up a path to use with RegOpenKeyEx.
    By which I mean that, the deeper you go, the bigger the path needs to get, it'll be empty at first but end up as, for example, "Software\2015\Mohaa".

    Hope that made sense as I am dutch after all
    =|UWS|=|SA|Vince - Head Serveradmin - mohaa.uwsclan.us (MOH:AA - FT)

  10. #10
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Ok updated some stuff:

    PHP Code:
    void q(HKEY hk, const char *kHWND hTest, const int pref)
    {
        
    char szBuffer[MAX_KEY_LENGTH];
        
    HKEY hKey;
        
    RegOpenKeyEx(hk,k,0,KEY_ALL_ACCESS,&hKey);
        
    DWORD cSubKeys;
        
    DWORD maxSubkeyLen;
        
    DWORD retCode;

        
    RegQueryInfoKey(hKeyNULLNULLNULL, &cSubKeys, &maxSubkeyLenNULLNULLNULLNULLNULLNULL);

        if(
    cSubKeys>0)
        {
            static 
    char currentSubkey[MAX_PATH];

            
    int i;
            for(
    i=0;cSubKeys;i++)
            {
                
    DWORD currentSubLen=MAX_PATH;

                
    retCode=RegEnumKeyEx(hKeyicurrentSubkey, &currentSubLenNULLNULLNULLNULL);

                if(
    retCode==ERROR_SUCCESS)
                {
                    
    char l[MAX_KEY_LENGTH];
                    static 
    char p[sizeof(prefix)];
                    
    snprintf(pMIN(prefsizeof(p)), "%s"prefix);
                    
    snprintf(lsizeof(l), "%s\\%s"kcurrentSubkey);

                    
    _stprintf_s(szBuffer"%s%s\n"pl);
                    
    SetWindowText(hTestszBuffer);

                    
    q(hklhTestpref 2);
                }
            }
        }

        
    RegCloseKey(hKey);

    I call it by passing this:
    PHP Code:
    q(HKEY_CURRENT_USER"Software\\Shoreline Teleworks"hTabView20); 
    Now this key has a bunch of sub categories under it (about 5), but when I print out the result it only prints the last one. Why???

    Here is the whole function:
    PHP Code:
    void CreateStaticViewTab2()
    {
        
    RECT tr = {0}; // rect structure to hold tab size

        // get the tab size info so we can place the view window in the right place
        
    TabCtrl_GetItemRect(hTab1, &tr);

        
    hTabView2 CreateWindowEx(0TEXT("STATIC"), TEXT(""), WS_CHILD WS_VISIBLE SS_LEFT200200600400,  hTabNULLhInstNULL);

        
    q(HKEY_CURRENT_USER"Software\\Shoreline Teleworks"hTabView20);

        
    CenterWindow(hTabView2hWnd500300);


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •