On 05/29/2013 04:11 AM, Albert-Jan Roskam wrote:
Hello,

I created a program to go through the windows registry and look for a certain key 
("file_locations", though in the example I am using a key that every windows user has on 
his/her computer). If found, I want to replace the data associated with value "temp_dir" 
in that key. I have chosen this strategy because the exact registry keys may have changed from 
version to version. Also, multiple versions of the program may be installed on a given computer. I 
pasted the code below this mail, but also here: http://pastebin.com/TEkyekfi

Is this the correct way to do this? I would actually prefer to specify only "valueNameToSearch" 
and not also "keyToSearch". As in: start walking through the registry starting at 
<regkey>, return every key where a temp_dir is defined.

Thank you in advance!


Regards,
Albert-Jan

Please specify Python version. I'll assume 2.7. Obviously this is Windows, though it's also conceivable that it matters which version of Windows (XP, Win8, whatever).

First comment is that I'd be writing walkRegistry as a generator, using yield for the items found, rather than building a list. It's generally easier to reuse that way, and won't get you in trouble if there are tons of matches. See os.walk for an example.

A generator also would naturally eliminate the need to know KeyToSearch.


import _winreg
import os

global __debug__
__debug__ = True

def walkRegistry(regkey, keyToSearch="file_locations",
                  valueNameToSearch="temp_dir", verbose=False):
     """Recursively search the Windows registry (HKEY_CURRENT_USER),
     starting at top <regkey>. Return a list of three tuples that contain
     the registry key, the value and the associated data"""
     if verbose:
         print regkey
     aReg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, regkey)
     i, keys, founds = 0, [], []
     try:
         while True:
             i += 1
             key = _winreg.EnumKey(aReg, i)

I believe these are zero-based indexes, so you're skipping the first one.

             keys.append(key)
             if key == keyToSearch:

If this were a generator, you'd not be restricting the key here. By restricting this key, you're limiting which subkeys you're going to search, and in the general case, I believe you're currently skipping values incorrectly.

                 keyx = os.path.join(regkey, key)
                 aReg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, keyx)

Unsure here, but having another open here feels wrong.

                 data, type_ = _winreg.QueryValueEx(aReg, valueNameToSearch)
                 founds.append((keyx, valueNameToSearch, data))

Generally, recursion should happen here, rather than building a list and doing the recursion below.

     except WindowsError:
         for key in keys:
             try:
                 new_regkey = os.path.join(regkey, key)
                 walkRegistry(new_regkey, keyToSearch,
                              valueNameToSearch, verbose)

Nesting exceptions makes me nervous, and doing it recursively, makes me even more so. If you move the recursion to the above area, then all the exception has to do is break out of the while loop.

             except WindowsError:
                 pass
     return founds

def setRegistry(regkey, keyToSet, valueToSet, replacementData, verbose=False):
     """Search for <keyToSet> starting at top <regkey>. If <keyToSet> is found
     exactly once, replace registry data associated with <valueToSet> with
     <replacementData>."""
     founds = walkRegistry(regkey, keyToSet, valueToSet, verbose)

If you changed walkRegistry as I suggest above, then this call becomes something like:
       for item in walkRegistry(regkey, keyToSet, valueToSet, verbose):


and inside the loop, you'll be testing the 'item' tuple for your criteria. The test is done here, and NOT in the walkRegistry() function.

     if not founds:
         return
     elif len(founds) == 1:
         keyx, valueNameToSearch, data = founds[0]
     else:
         msg = "Registry value %r is found multiple times"
         raise ValueError(msg % valueToSet)

     if not __debug__:
         try:
             key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, keyx,
                                   0, _winreg.KEY_ALL_ACCESS)
         except:
             key = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, regkey)
         _winreg.SetValueEx(keyx, valueToSet, 0, _winreg.REG_SZ,
                            replacementData)
         _winreg.CloseKey(keyx)

regkey = u"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"
print founds = walkRegistry(regkey, u"Shell Folders", u"Cookies", True)
setRegistry(regkey, u"Shell Folders", u"Cookies", "this is the replacement 
value", False)




--
DaveA
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to