Scanning through Windows registry...

U

Unknown Hero

Hi everyone!

Well, I have this need for a Python script that will scan through a
selected hive (like HKEY_LOCAL_MACHINE) and replace all strings that
contain word xxx (IE. foo) with yyy (IE. moo). I do not want partial
results, but rather complete strings (no foome or the like, just foo).


I have a basic understanding of Python, but this is beyond my skills.

I was looking for something like this:

open key (HKEY_LOCAL_MACHINE)
while (not end of list)
open next subkey
search subkey for value (old)
SetValue(key, subkey, REG_SZ, new)
close subkey
end while
close key
 
T

Tim Golden

Unknown said:
Hi everyone!

Well, I have this need for a Python script that will scan through a
selected hive (like HKEY_LOCAL_MACHINE) and replace all strings that
contain word xxx (IE. foo) with yyy (IE. moo). I do not want partial
results, but rather complete strings (no foome or the like, just foo).


I have a basic understanding of Python, but this is beyond my skills.

I was looking for something like this:

open key (HKEY_LOCAL_MACHINE)
while (not end of list)
open next subkey
search subkey for value (old)
SetValue(key, subkey, REG_SZ, new)
close subkey
end while
close key

In a spirit of teaching people to fish...

.... If you put something like "Python windows registry" into Google, you
get quite a few hits, the top one of which is probably pointing to the stdlib
_winreg module, but several others point towards wrapper classes, modules
etc. which provide a simpler or at least a different interface to the registry.

Have a look at those and see if you can't work out what to do.

TJG
 
U

Unknown Hero

Tim said:
In a spirit of teaching people to fish...

... If you put something like "Python windows registry" into Google, you
get quite a few hits, the top one of which is probably pointing to the stdlib
_winreg module, but several others point towards wrapper classes, modules
etc. which provide a simpler or at least a different interface to the registry.

Have a look at those and see if you can't work out what to do.

TJG

The first link which points to the Python documentation for the
_winreg module I already checked, even before coming here. I am
wondering how I should do the loop I need (go through
HKEY_LOCAL_MACHINE and read one subkey at a time, if it contains this
'foo' then change it into 'moo'). As I already said, I am by no means
an expert in Python (heck, I learned the basics only a month ago).
However, I am willing to learn.

Also my prior experience with the Windows registry is mostly by the
Registry Editor shipped with Windows. While I do understand what keys,
values and hives are, I do not have a great experience in the others.

If it's not too much to ask, maybe someone (who is much better than
me) could make a code snippet that reads a certain hive and replaces
values that are predetermined (preferably variables, not arguments if
possible).

If that's out of the question, at least push me gently into the right
direction.

So basically I am looking for these things:

1) Read one subkey from HKEY_LOCAL_MACHINE at a time (I think
QueryValueEx() is needed here)
2) Check if said subkey contains some predetermined string (like 'foo'
here)
3) If the above applies, change the value into another predetermined
string (like 'moo' here)


Also, how should I determine the length of the loop? I personally am
too fond of the for loop, but if I need to use, like, while, then so
be it.

Thanks in advance.
 
T

Tim Golden

Unknown said:
So basically I am looking for these things:

1) Read one subkey from HKEY_LOCAL_MACHINE at a time (I think
QueryValueEx() is needed here)
2) Check if said subkey contains some predetermined string (like 'foo'
here)
3) If the above applies, change the value into another predetermined
string (like 'moo' here)

Well, I attach a kind of explanatory Noddy example I wrote a few years ago
for someone on the python-win32 list. I think, glancing over it, that it includes
what you need to know, although not necessarily in the right order. I'm happy to
explain if things aren't clear:

<code>
import _winreg

HKLM = _winreg.HKEY_LOCAL_MACHINE

#
# Set up a registry subtree under HKLM\Software
# which will look like this:
#

#
# TimSoft
# |
# +-- App1
# |
# +-- App2
# |
# +-- App3
#

#
# The [TimSoft] key has a default (ie unnamed) value
# while the Appx keys each have two values:
# [Registered] - a string Y/N value
# [Version] - a DWORD value
#

hSoftware = _winreg.OpenKey (HKLM, "Software")
hTimSoft = _winreg.CreateKey (hSoftware, "TimSoft")

_winreg.SetValueEx (hTimSoft, None, 0, _winreg.REG_SZ, "All Tim's Software")

hApp1 = _winreg.CreateKey (hTimSoft, "App1")
_winreg.SetValueEx (hApp1, "Version", 0, _winreg.REG_DWORD, 101)
_winreg.SetValueEx (hApp1, "Registered", 0, _winreg.REG_SZ, "Y")

hApp2 = _winreg.CreateKey (hTimSoft, "App2")
_winreg.SetValueEx (hApp2, "Version", 0, _winreg.REG_DWORD, 202)
_winreg.SetValueEx (hApp2, "Registered", 0, _winreg.REG_SZ, "N")

hApp3 = _winreg.CreateKey (hTimSoft, "App3")
_winreg.SetValueEx (hApp3, "Version", 0, _winreg.REG_DWORD, 303)
_winreg.SetValueEx (hApp3, "Registered", 0, _winreg.REG_SZ, "Y")

#
# NB - no need to do an explicit "write": the Registry uses
# some sort of caching which eventually catches up with itself,
# so unless you plan to turn the machine off soon, don't
# bother with FlushKey or anything like that.
#

#
# Now we start again, as though we were just querying
#

hTimSoft = _winreg.OpenKey (HKLM, r"Software\TimSoft")
n_sub_keys, n_values, last_modified = _winreg.QueryInfoKey (hTimSoft)
print n_sub_keys, "sub keys", n_values, "values", last_modified, "nanoseconds since 1600!"

#
# Pick up the default value: really should try to
# interpret the default_type to determine if it's
# a number or a string or whatever, but...
#
default_value, default_type = _winreg.QueryValueEx (hTimSoft, None)
print "Default value:", default_value

#
# Now, in this case I know (because I created them) that
# the TimSoft key has three subkeys, each of which has
# two values. But if I didn't...
#
print
for i in range (n_sub_keys):
subkey_name = _winreg.EnumKey (hTimSoft, i)
print subkey_name

#
# Alternatively, if I hadn't done the QueryInfoKey above...
#
i = 0
print
while 1:
try:
subkey_name = _winreg.EnumKey (hTimSoft, i)
except EnvironmentError:
break
else:
print subkey_name
i += 1

#
# Now, let's use the last key as an example
# and pick out its values.
#
print
print subkey_name
hAppKey = _winreg.OpenKey (hTimSoft, subkey_name)
i = 0
while 1:
try:
name, value, type = _winreg.EnumValue (hAppKey, i)
print name, value, type
except EnvironmentError:
break
else:
print " %s => %s (type %s)" % (name, value, type)
i += 1

</code>

TJG
 
U

Unknown Hero

Tim said:
Well, I attach a kind of explanatory Noddy example I wrote a few years ago
for someone on the python-win32 list. I think, glancing over it, that it includes
what you need to know, although not necessarily in the right order. I'm happy to
explain if things aren't clear:

<code>
import _winreg

HKLM = _winreg.HKEY_LOCAL_MACHINE

#
# Set up a registry subtree under HKLM\Software
# which will look like this:
#

#
# TimSoft
# |
# +-- App1
# |
# +-- App2
# |
# +-- App3
#

#
# The [TimSoft] key has a default (ie unnamed) value
# while the Appx keys each have two values:
#   [Registered] - a string Y/N value
#   [Version] - a DWORD value
#

hSoftware = _winreg.OpenKey (HKLM, "Software")
hTimSoft = _winreg.CreateKey (hSoftware, "TimSoft")

_winreg.SetValueEx (hTimSoft, None, 0, _winreg.REG_SZ, "All Tim's Software")

hApp1 = _winreg.CreateKey (hTimSoft, "App1")
_winreg.SetValueEx (hApp1, "Version", 0, _winreg.REG_DWORD, 101)
_winreg.SetValueEx (hApp1, "Registered", 0, _winreg.REG_SZ, "Y")

hApp2 = _winreg.CreateKey (hTimSoft, "App2")
_winreg.SetValueEx (hApp2, "Version", 0, _winreg.REG_DWORD, 202)
_winreg.SetValueEx (hApp2, "Registered", 0, _winreg.REG_SZ, "N")

hApp3 = _winreg.CreateKey (hTimSoft, "App3")
_winreg.SetValueEx (hApp3, "Version", 0, _winreg.REG_DWORD, 303)
_winreg.SetValueEx (hApp3, "Registered", 0, _winreg.REG_SZ, "Y")

#
# NB - no need to do an explicit "write": the Registry uses
#  some sort of caching which eventually catches up with itself,
#  so unless you plan to turn the machine off soon, don't
#  bother with FlushKey or anything like that.
#

#
# Now we start again, as though we were just querying
#

hTimSoft = _winreg.OpenKey (HKLM, r"Software\TimSoft")
n_sub_keys, n_values, last_modified = _winreg.QueryInfoKey (hTimSoft)
print n_sub_keys, "sub keys", n_values, "values", last_modified, "nanoseconds since 1600!"

#
# Pick up the default value: really should try to
#  interpret the default_type to determine if it's
#  a number or a string or whatever, but...
#
default_value, default_type = _winreg.QueryValueEx (hTimSoft, None)
print "Default value:", default_value

#
# Now, in this case I know (because I created them) that
#  the TimSoft key has three subkeys, each of which has
#  two values. But if I didn't...
#
print
for i in range (n_sub_keys):
  subkey_name = _winreg.EnumKey (hTimSoft, i)
  print subkey_name

#
# Alternatively, if I hadn't done the QueryInfoKey above...
#
i = 0
print
while 1:
  try:
    subkey_name = _winreg.EnumKey (hTimSoft, i)
  except EnvironmentError:
    break
  else:
    print subkey_name
    i += 1

#
# Now, let's use the last key as an example
#  and pick out its values.
#
print
print subkey_name
hAppKey = _winreg.OpenKey (hTimSoft, subkey_name)
i = 0
while 1:
  try:
    name, value, type = _winreg.EnumValue (hAppKey, i)
    print name, value, type
  except EnvironmentError:
    break
  else:
    print "  %s => %s (type %s)" % (name, value, type)
    i += 1

</code>

TJG

Correct me if I'm wrong (which I just might be), but doesn't the above
code go through the keys behind HKEY_LOCAL_MACHINE\Software\Timsoft\ ?

Is it possible to use an empty value in:

hTimSoft = _winreg.OpenKey (HKLM, r"Software\TimSoft")

like:

hTimSoft = _winreg.OpenKey (HKLM, "")

so it would go all subkeys behind the "root" (in this case,
HKEY_LOCAL_MACHINE)?


The code is supposed to work even if I don't know all possible subkeys
under HKEY_LOCAL_MACHINE. Creating dozens or hundreds of handles like
the above is a bit... unappealing.

Can I also use HKLM in the place of hTimSoft when I want to determine
the amount of subkeys it has, like you did over here:

n_sub_keys, n_values, last_modified = _winreg.QueryInfoKey
(hTimSoft)


Anyway, the above code seems interesting. I'll try a few tweaks here
and there and see what happens.

Thank you, Tim.
 
T

Tim Golden

Unknown said:
Tim Golden wrote:

[... snip long example ...]
Correct me if I'm wrong (which I just might be), but doesn't the above
code go through the keys behind HKEY_LOCAL_MACHINE\Software\Timsoft\ ?

Is it possible to use an empty value in:

hTimSoft = _winreg.OpenKey (HKLM, r"Software\TimSoft")

like:

hTimSoft = _winreg.OpenKey (HKLM, "")

so it would go all subkeys behind the "root" (in this case,
HKEY_LOCAL_MACHINE)?

Yes. (Well, you can try it and find out for yourself!). As I said, this
was code to illustrate some other poster's difficulty. I assume that
you're capable of twisting it to suit your own purposes :)
The code is supposed to work even if I don't know all possible subkeys
under HKEY_LOCAL_MACHINE. Creating dozens or hundreds of handles like
the above is a bit... unappealing.

Can I also use HKLM in the place of hTimSoft when I want to determine
the amount of subkeys it has, like you did over here:

Yes. You can put any key handle you like in place of my
hTimSoft of the predefined _winreg.HKEY_LOCAL_MACHINE. They're
just keys. I assume you'll want some kind of recursive function which
combines calls to EnumKeys and EnumValues.
Anyway, the above code seems interesting. I'll try a few tweaks here
and there and see what happens.

I wasn't sure just how experienced you were with programming; although you
said you were new to Python I thought you might have experience elsewhere
which would help you out here. If you're really stuck, post back and I (or someone
else) can try to knock up a more pertinent example. The main thing is for you
to get hold of the _winreg docs -- which I know you mentioned before -- and to
grasp what the concepts are and how the API calls work. It's a low-level module,
simply exposing the raw API calls, which is why there are several wrapper modules
around it, but it's worth getting to understand what's going on under the covers.

TJG
 
T

Tim Golden

In a spirit of being helpful... :)

The code below (which I imagine every Windows programmer writes
sometime in their Python life) mimics the os.walk functionality, yielding
the key, subkeys, and values under a particular starting point in the
registry. The "if __name__ == '__main__'" test run at the bottom does
more-or-less what you were asking for originally, I think, converting
some name to some other name wherever it appears.

<module regwalk.py>
import _winreg

HIVES = {
"HKEY_LOCAL_MACHINE" : _winreg.HKEY_LOCAL_MACHINE,
"HKEY_CURRENT_USER" : _winreg.HKEY_CURRENT_USER,
"HKEY_CLASSES_ROOT" : _winreg.HKEY_CLASSES_ROOT,
"HKEY_USERS" : _winreg.HKEY_USERS,
"HKEY_CURRENT_CONFIG" : _winreg.HKEY_CURRENT_CONFIG
}

class RegKey:

def __init__ (self, name, key):
self.name = name
self.key = key

def __str__ (self):
return self.name

def walk (top):
"""walk the registry starting from the key represented by
top in the form HIVE\\key\\subkey\\..\\subkey and generating
key, subkey_names, values at each level.

key is a lightly wrapped registry key, including the name
and the HKEY object.
subkey_names are simply names of the subkeys of that key
values are 3-tuples containing (name, data, data-type).
See the documentation for _winreg.EnumValue for more details.
"""
if "\\" not in top: top += "\\"
root, subkey = top.split ("\\", 1)
key = _winreg.OpenKey (HIVES[root], subkey, 0, _winreg.KEY_READ | _winreg.KEY_SET_VALUE)

subkeys = []
i = 0
while True:
try:
subkeys.append (_winreg.EnumKey (key, i))
i += 1
except EnvironmentError:
break

values = []
i = 0
while True:
try:
values.append (_winreg.EnumValue (key, i))
i += 1
except EnvironmentError:
break

yield RegKey (top, key), subkeys, values

for subkey in subkeys:
for result in walk (top + "\\" + subkey):
yield result

if __name__ == '__main__':
for key, subkey_names, values in walk ("HKEY_LOCAL_MACHINE\\Software\\Python"):
print key
for (name, data, type) in values:
print " ", name, "=>", data
if type == _winreg.REG_SZ and "TJG" in data:
_winreg.SetValueEx (key.key, name, 0, type, data.replace ("TJG", "XYZ"))

</module regwalk.py>

TJG
 
U

Unknown Hero

Thank you, I think I can manage now. It's nice that you could spare
some time to help me in this, Tim. People like you make the world a
better place :)

I'll post my code here once I have time to write it, currently I'm
rather busy. That is merely for optimization suggestions and for
others who might need the same sort of code I did.


Thank you once again.
 
M

Mike Driscoll

In a spirit of being helpful... :)

The code below (which I imagine every Windows programmer writes
sometime in their Python life) mimics the os.walk functionality, yielding
the key, subkeys, and values under a particular starting point in the
registry. The "if __name__ == '__main__'" test run at the bottom does
more-or-less what you were asking for originally, I think, converting
some name to some other name wherever it appears.

<module regwalk.py>
import _winreg

HIVES = {
  "HKEY_LOCAL_MACHINE" : _winreg.HKEY_LOCAL_MACHINE,
  "HKEY_CURRENT_USER" : _winreg.HKEY_CURRENT_USER,
  "HKEY_CLASSES_ROOT" : _winreg.HKEY_CLASSES_ROOT,
  "HKEY_USERS" : _winreg.HKEY_USERS,
  "HKEY_CURRENT_CONFIG" : _winreg.HKEY_CURRENT_CONFIG

}

class RegKey:

  def __init__ (self, name, key):
     self.name = name
     self.key = key

  def __str__ (self):
    return self.name

def walk (top):
  """walk the registry starting from the key represented by
  top in the form HIVE\\key\\subkey\\..\\subkey and generating
  key, subkey_names, values at each level.

  key is a lightly wrapped registry key, including the name
  and the HKEY object.
  subkey_names are simply names of the subkeys of that key
  values are 3-tuples containing (name, data, data-type).
  See the documentation for _winreg.EnumValue for more details.
  """
  if "\\" not in top: top += "\\"
  root, subkey = top.split ("\\", 1)
  key = _winreg.OpenKey (HIVES[root], subkey, 0, _winreg.KEY_READ | _winreg.KEY_SET_VALUE)

  subkeys = []
  i = 0
  while True:
    try:
      subkeys.append (_winreg.EnumKey (key, i))
      i += 1
    except EnvironmentError:
      break

  values = []
  i = 0
  while True:
    try:
      values.append (_winreg.EnumValue (key, i))
      i += 1
    except EnvironmentError:
      break

  yield RegKey (top, key), subkeys, values

  for subkey in subkeys:
    for result in walk (top + "\\" + subkey):
      yield result

if __name__ == '__main__':
  for key, subkey_names, values in walk ("HKEY_LOCAL_MACHINE\\Software\\Python"):
    print key
    for (name, data, type) in values:
      print "  ", name, "=>", data
      if type == _winreg.REG_SZ and "TJG" in data:
        _winreg.SetValueEx (key.key, name, 0, type, data.replace ("TJG", "XYZ"))

</module regwalk.py>

TJG

This is pretty cool stuff, Tim. Of course, it would also seriously
screw up some programs if you decided to replace the wrong phrase.
Just a word of warning to the OP: be sure to make a backup of the
registry before doing something like this. Trying to fix a messed up
registry from the command line is not a fun way to spend the
afternoon.

Mike
 
T

Tim Golden

[... snip registry walker ...]
This is pretty cool stuff, Tim. Of course, it would also seriously
screw up some programs if you decided to replace the wrong phrase.
Just a word of warning to the OP: be sure to make a backup of the
registry before doing something like this. Trying to fix a messed up
registry from the command line is not a fun way to spend the
afternoon.

Good point, Mike. In a spirit of being even more helpful... the _winreg
module includes the functions SaveKey and LoadKey so as a crude
backup mechanism, you could do this:

<code snippet>
import time
import _winreg
import win32api
import win32security

#
# You need to have SeBackupPrivilege enabled for this to work
#
priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess (), priv_flags)
privilege_id = win32security.LookupPrivilegeValue (None, "SeBackupPrivilege")
win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)])

root = _winreg.OpenKey (_winreg.HKEY_LOCAL_MACHINE, r"Software\Python\TEST")
#
# This will fail if the file already exists so make it uniqueish
#
_winreg.SaveKey (root, "c:/temp/HKLM_Software_Python-%s.reg" % time.strftime ("%Y%m%d-%H%M%S"))

</code snippet>

Note that the file which this creates is *not* the same as a .reg file which the File > Export menu
option provides from within the registry editor. (In fact, I shouldn't really have called it .reg; call
it something else). It can be reloaded by the _winreg.LoadKey function -- which I notice is incorrectly
named RegLoadKey in the docs after the underlying API call. The docs note that SeRestorePrivilege is
required for this action, the counterpart to SeBackupPrivilege.

TJG
 
M

Mike Driscoll

[... snip registry walker ...]
This is pretty cool stuff, Tim. Of course, it would also seriously
screw up some programs if you decided to replace the wrong phrase.
Just a word of warning to the OP: be sure to make a backup of the
registry before doing something like this. Trying to fix a messed up
registry from the command line is not a fun way to spend the
afternoon.

Good point, Mike. In a spirit of being even more helpful... the _winreg
module includes the functions SaveKey and LoadKey so as a crude
backup mechanism, you could do this:

<code snippet>
import time
import _winreg
import win32api
import win32security

#
# You need to have SeBackupPrivilege enabled for this to work
#
priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess (), priv_flags)
privilege_id = win32security.LookupPrivilegeValue (None, "SeBackupPrivilege")
win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)])

root = _winreg.OpenKey (_winreg.HKEY_LOCAL_MACHINE, r"Software\Python\TEST")
#
# This will fail if the file already exists so make it uniqueish
#
_winreg.SaveKey (root, "c:/temp/HKLM_Software_Python-%s.reg" %  time.strftime ("%Y%m%d-%H%M%S"))

</code snippet>

Note that the file which this creates is *not* the same as a .reg file which the File > Export menu
option provides from within the registry editor. (In fact, I shouldn't really have called it .reg; call
it something else). It can be reloaded by the _winreg.LoadKey function -- which I notice is incorrectly
named RegLoadKey in the docs after the underlying API call. The docs note that SeRestorePrivilege is
required for this action, the counterpart to SeBackupPrivilege.

TJG

Wow! Talk about going above and beyond the call of tutoring! I still
don't know how you found out how to do all these neat Windows tricks,
but I'll be filing them away for future reference.

Mike
 
U

Unknown Hero

I'll post my code here once I have time to write it, currently I'm
rather busy. That is merely for optimization suggestions and for
others who might need the same sort of code I did.

Thank you once again.

Finally managed to get it to work (heh, I was pretty darn lost even
though I had the best help) but as promised, I'll post my code here
for those who might be interested in it. The biggest of thanks to Tim
Golden, who basically walked me step-by-step through this. Most of the
code is copied from his examples above.

<code snippet>
#Goes through all keys and subkeys in the selected hive (defined as
root) and replaces the value 'old' with the value 'new'
#
#IMPORTANT! You should always back up the registry before attempting
to modify it.
#The author of this script CANNOT BE HELD RESPONSIVE for any damage
caused by running this script.
#
#To customize the script to your liking, you can alter the values old,
new, root.
#
#old and new can be any string value
#root has to be one of the following:
#
# _winreg.HKEY_LOCAL_MACHINE
# _winreg.HKEY_CURRENT_USER
# _winreg.HKEY_CLASSES_ROOT
# _winreg.HKEY_USERS
# _winreg.HKEY_CURRENT_CONFIG

import _winreg

HIVES = {
"HKEY_LOCAL_MACHINE" : _winreg.HKEY_LOCAL_MACHINE,
"HKEY_CURRENT_USER" : _winreg.HKEY_CURRENT_USER,
"HKEY_CLASSES_ROOT" : _winreg.HKEY_CLASSES_ROOT,
"HKEY_USERS" : _winreg.HKEY_USERS,
"HKEY_CURRENT_CONFIG" : _winreg.HKEY_CURRENT_CONFIG

}

old = "This was value before"
new = "This is new value"

start = "HKEY_LOCAL_MACHINE\\"
startHandle = _winreg.HKEY_LOCAL_MACHINE

#Values for start and startHandle are: HKEY_LOCAL_MACHINE,
HKEY_CURRENT_USER, HKEY_CLASSES_ROOT, HKEY_USERS, HKEY_CURRENT_CONFIG


class RegKey:

def __init__ (self, name, key):
self.name = name
self.key = key

def __str__ (self):
return self.name

def walk (top):
"""walk the registry starting from the key represented by
top in the form HIVE\\key\\subkey\\..\\subkey and generating
key, subkey_names, values at each level.

key is a lightly wrapped registry key, including the name
and the HKEY object.
subkey_names are simply names of the subkeys of that key
values are 3-tuples containing (name, data, data-type).
See the documentation for _winreg.EnumValue for more details.
"""
try:
if "\\" not in top: top += "\\"
root, subkey = top.split ("\\", 1)
# print "KEY:", root + "\\" + subkey
key = _winreg.OpenKey (HIVES[root], subkey, 0, _winreg.KEY_READ |
_winreg.KEY_SET_VALUE)
subkeys = []
i = 0
while True:
try:
subkeys.append (_winreg.EnumKey (key, i))
i += 1
except EnvironmentError:
break

values = []
i = 0
while True:
try:
values.append (_winreg.EnumValue (key, i))
i += 1
except EnvironmentError:
break

yield RegKey (top, key), subkeys, values

for subkey in subkeys:
for result in walk (top + "\\" + subkey):
yield result

except WindowsError:
# print 'Could not open key', root + "\\" + subkey + "\n"
pass

basickeys = []
i = 0
while True:
try:
basickeys.append (_winreg.EnumKey (startHandle, i))
i += 1
except EnvironmentError:
print i, 'subkeys found!'
break

for x in range(len(basickeys)):
for key, subkey_names, values in walk (start + basickeys[x]):
# print key
for (name, data, type) in values:
# print " ", name, "=>", data
if type == _winreg.REG_SZ and old in data:
_winreg.SetValueEx (key.key, name, 0, type, data.replace (old,
new))
</code>


Not the most effecient code, I'm sure, but it does what I want it to
do :D

Thank you once more, Tim. Also, thank you, Mike, for your advice on
saving the registry. I would have forgotten to note backing up the
registry in the beginning if it wasn't for you bringing that up. :D
 
U

Unknown Hero

Finally managed to get it to work (heh, I was pretty darn lost even
though I had the best help) but as promised, I'll post my code here
for those who might be interested in it. The biggest of thanks to Tim
Golden, who basically walked me step-by-step through this. Most of the
code is copied from his examples above.

[large piece of code here]

Not the most effecient code, I'm sure, but it does what I want it to
do :D

Thank you once more, Tim. Also, thank you, Mike, for your advice on
saving the registry. I would have forgotten to note backing up the
registry in the beginning if it wasn't for you bringing that up. :D

Hmm... Improving your code is always fun :D but quick fixes to make it
replace search results that contain something more than 'old' here
don't
seem to work.

So I made it command-line, with arguments Hive, old, new.

If I ran the script as registry.py HKEY_LOCAL_MACHINE something
"something else"
and I had made dummy values to the registry like "there is something
here" it
won't update to "there is something else here".

I tried this, can Tim (or someone else) possibly help?

if type == _winreg.REG_SZ:
Character = 0
Correct = 0
FoundStart = FoundEnd = 0
Found = False
for y in range(len(data)):
if Character < len(old):
if old[Character] is data[y]:
Character = Character + 1
Correct = Correct + 1
if Correct is len(old):
Found = True
Replace = ""
Character = 0
for y in range(len(data)):
if old[0] is data[y]:
FoundStart = int(y)
FoundEnd = FoundStart + oldLength
for y in range(FoundStart):
Replace = Replace + data[y]

for y in range(len(new)):
Replace = Replace + new[y]

for y in range(FoundEnd, len(data)):
Replace = Replace + data[y]

if Found:
_winreg.SetValueEx (key.key, name, 0, type, data.replace
(old, Replace))


Thanks in advance.
 
U

Unknown Hero

Ah, never mind, got it to work. Here's the code now. I hope I won't
run into another problems later :D


<code snippet>
#Goes through all keys and subkeys in the selected hive (defined as
root) and replaces the value 'old' with the value 'new'
#
#IMPORTANT! You should always back up the registry before attempting
to modify it.
#The author of this script CANNOT BE HELD RESPONSIVE for any damage
caused by running this script.
#
#To customize the script to your liking, you can alter the values old,
new, root.
#
#old and new can be any string value
#root has to be one of the following:
#
# _winreg.HKEY_LOCAL_MACHINE
# _winreg.HKEY_CURRENT_USER
# _winreg.HKEY_CLASSES_ROOT
# _winreg.HKEY_USERS
# _winreg.HKEY_CURRENT_CONFIG

import _winreg #For accessing windows registry, included in Python
2.0.
import sys #For reading arguments (command line), included in every
Python release.

HIVES = {
"HKEY_LOCAL_MACHINE" : _winreg.HKEY_LOCAL_MACHINE,
"HKEY_CURRENT_USER" : _winreg.HKEY_CURRENT_USER,
"HKEY_CLASSES_ROOT" : _winreg.HKEY_CLASSES_ROOT,
"HKEY_USERS" : _winreg.HKEY_USERS,
"HKEY_CURRENT_CONFIG" : _winreg.HKEY_CURRENT_CONFIG
}


class RegKey:

def __init__ (self, name, key):
self.name = name
self.key = key

def __str__ (self):
return self.name

def walk (top):
"""walk the registry starting from the key represented by
top in the form HIVE\\key\\subkey\\..\\subkey and generating
key, subkey_names, values at each level.

key is a lightly wrapped registry key, including the name
and the HKEY object.
subkey_names are simply names of the subkeys of that key
values are 3-tuples containing (name, data, data-type).
See the documentation for _winreg.EnumValue for more details.
"""
try:
if "\\" not in top: top += "\\"
root, subkey = top.split ("\\", 1)
# print "KEY:", root + "\\" + subkey
key = _winreg.OpenKey (HIVES[root], subkey, 0, _winreg.KEY_READ |
_winreg.KEY_SET_VALUE)
subkeys = []
i = 0
while True:
try:
subkeys.append (_winreg.EnumKey (key, i))
i += 1
except EnvironmentError:
break

values = []
i = 0
while True:
try:
values.append (_winreg.EnumValue (key, i))
i += 1
except EnvironmentError:
break

yield RegKey (top, key), subkeys, values

for subkey in subkeys:
for result in walk (top + "\\" + subkey):
yield result

except WindowsError:
# print 'Could not open key', root + "\\" + subkey + ", access
denied!\n"
pass

except:
print 'Other error!'


def main(start, startHandle, old, new):
basickeys = []
i = 0
while True:
try:
basickeys.append (_winreg.EnumKey (startHandle, i))
i += 1
except EnvironmentError:
# print i, 'subkeys found!'
break

for x in range(len(basickeys)):
for key, subkey_names, values in walk (start + "\\" +
basickeys[x]):
# print key
for (name, data, type) in values:
# print " ", name, "=>", data
if type == _winreg.REG_SZ:
Character = 0
Correct = 0
FoundStart = FoundEnd = 0
Found = False
for y in range(len(data)):
try:
if Character < len(old):
# print old[Character], data[y]
if old[Character] in data[y]:
Character = Character + 1
Correct = Correct + 1
except:
pass
if Correct is len(old):
# print 'Debug!'
Replace = ""
Character = 0
for y in range(len(data)):
if not Found:
if old[0] in data[y]:
FoundStart = int(y)
FoundEnd = FoundStart + len(old)
Found = True
# for y in range(FoundStart):
# Replace = Replace + data[y]

for y in range(len(new)):
Replace = Replace + new[y]

# for y in range(FoundEnd, len(data)):
# Replace = Replace + data[y]
Found = True
if Found:
# print "OLD:", old, "will be replaced with:", Replace
_winreg.SetValueEx (key.key, name, 0, type, data.replace
(old, Replace))


def help():
#Show help
print 'USAGE: Registry.py [HIVE] [OLD] [NEW]'
print ' HIVE: The root key in registry you want to go through.'
print ' HKEY_CLASSES_ROOT'
print ' HKEY_CURRENT_USER'
print ' HKEY_LOCAL_MACHINE'
print ' HKEY_USERS'
print ' HKEY_CURRENT_CONFIG'
print ''
print ' OLD: The value to search for.'
print ' Wrap multiword strings with \"\".'
print ''
print ' NEW: The value which will replace OLD.'
print ' Wrap multiword strings with \"\".'

#Check for arguments
#HIVE, old, new

while True:
#Check if invalid number of arguments are given
if len(sys.argv) is 1:
help()
break

# for x in range(len(sys.argv)):
# print 'sys.argv[' + str(x) + ']:', sys.argv[x]

#Check if hive is first
if sys.argv[1].upper() in ('HKEY_CURRENT_USER',
'HKEY_LOCAL_MACHINE',
'HKEY_CLASSES_ROOT',
'HKEY_USERS',
'HKEY_CURRENT_CONFIG'):

start = sys.argv[1].upper()

else:
help()
break

#Check that not only one argument is given (at least two required,
preferably three)
if len(sys.argv) is 2:
help()
break

old = sys.argv[2]

if len(sys.argv) is 4:
new = sys.argv[3]

else:
help()
break


if start in ('HKEY_CLASSES_ROOT'):
startHandle = _winreg.HKEY_CLASSES_ROOT

elif start in ('HKEY_CURRENT_USER'):
startHandle = _winreg.HKEY_CURRENT_USER

elif start in ('HKEY_LOCAL_MACHINE'):
startHandle = _winreg.HKEY_LOCAL_MACHINE

elif start in ('HKEY_USERS'):
startHandle = _winreg.HKEY_USERS

elif start in ('HKEY_CURRENT_CONFIG'):
startHandle = _winreg.HKEY_CURRENT_CONFIG

else:
help()
break

main(start, startHandle, old, new)
break
</code>
 
L

Lie

Ah, never mind, got it to work. Here's the code now. I hope I won't
run into another problems later :D

<code snippet>
#Goes through all keys and subkeys in the selected hive (defined as
root) and replaces the value 'old' with the value 'new'
#
#IMPORTANT! You should always back up the registry before attempting
to modify it.
#The author of this script CANNOT BE HELD RESPONSIVE for any damage
caused by running this script.
(snip)

One thing though, the disclaimer should not said the author cannot be
held responsive, or you would be Windows that is not responsive all
the times. I think it should say "responsible".

I'm quite confused though, the code could be made simpler by dozens
using Python's high-level functionalities. Particularly the lengthy
code that checked whether the string contained a substring and replace
the substring with new could be done easily (and faster) using
python's in and replace function. I'll post the code later when I
finished checking places where the codes could be simplified, and I'll
also polish the entry code and a few other things (and pythonify the
code according to the PEP 8's guide lines).
 
L

Lie

(snip)

One thing though, the disclaimer should not said the author cannot be
held responsive, or you would be Windows that is not responsive all
the times. I think it should say "responsible".

I'm quite confused though, the code could be made simpler by dozens
using Python's high-level functionalities. Particularly the lengthy
code that checked whether the string contained a substring and replace
the substring with new could be done easily (and faster) using
python's in and replace function. I'll post the code later when I
finished checking places where the codes could be simplified, and I'll
also polish the entry code and a few other things (and pythonify the
code according to the PEP 8's guide lines).

The tidied code ++

'''
Goes through all keys and subkeys in the selected hive (defined
as root) and replaces the value 'old' with the value 'new'

IMPORTANT! You should always back up the registry before
attempting to modify it. The author of this script CANNOT BE
HELD RESPONSIBLE for any damage caused by running this script.

You can call the script from a command line and pass two or
three values: HIVE, OLD, and NEW.

OLD and NEW can be any string value
HIVE has to be one of the following:

HKEY_LOCAL_MACHINE / HKLM
HKEY_CURRENT_USER / HKCU
HKEY_CLASSES_ROOT / HKCR
HKEY_USERS / HKU
HKEY_CURRENT_CONFIG / HKCC

If NEW is not specified, values that matches OLD will be replaced
with empty string (i.e. deleted)
'''

import _winreg
import sys

HIVES = {
"HKEY_LOCAL_MACHINE" : _winreg.HKEY_LOCAL_MACHINE,
"HKEY_CURRENT_USER" : _winreg.HKEY_CURRENT_USER,
"HKEY_CLASSES_ROOT" : _winreg.HKEY_CLASSES_ROOT,
"HKEY_USERS" : _winreg.HKEY_USERS,
"HKEY_CURRENT_CONFIG" : _winreg.HKEY_CURRENT_CONFIG,
}

AccessError = False

class RegKey(object):
def __init__ (self, name, key):
self.name = name
self.key = key

def __str__ (self):
return self.name

def walk(top):
""" Walk through each key, subkey, and values

Walk the registry starting from the key top
in the form HIVE\\key\\subkey\\..\\subkey and generating
key, subkey_names, values at each level.

key is a lightly wrapped registry key, including the name
and the HKEY object.
subkey_names are simply names of the subkeys of that key
values are 3-tuples containing (name, data, data-type).
See the documentation for _winreg.EnumValue for more details.
"""

try:
if "\\" not in top:
top += "\\"
root, subkey = top.split ("\\", 1)
key = _winreg.OpenKey(HIVES[root],
subkey,
0,
_winreg.KEY_READ |
_winreg.KEY_SET_VALUE)

subkeys = []
i = 0
while True:
try:
subkeys.append(_winreg.EnumKey(key, i))
i += 1
except EnvironmentError:
break

values = []
i = 0
while True:
try:
values.append(_winreg.EnumValue(key, i))
i += 1
except EnvironmentError:
break

yield RegKey(top, key), subkeys, values

for subkey in subkeys:
for result in walk(top + "\\" + subkey):
yield result

except WindowsError:
global AccessError
AccessError = True



def main(start, startHandle, old, new):
basickeys = []
i = 0
while True:
try:
basickeys.append(_winreg.EnumKey(startHandle, i))
i += 1
except EnvironmentError:
break

for x in basickeys:
for key, subkey_names, values in walk(start + "\\" + x):
for (name, data, type) in values:
if type == _winreg.REG_SZ:
if old in data:
winreg.SetValueEx(key.key,
name,
0,
type,
data.replace(old, new))
print key.key, name, 0, type,
data.replace(old, new)

def help():
#Show help
print '''
USAGE: Registry.py HIVE OLD [NEW]
HIVE: The root key in registry you want to go through.
HKEY_CLASSES_ROOT / HKCR
HKEY_CURRENT_USER / HKCU
HKEY_LOCAL_MACHINE / HKLM
HKEY_USERS / HKU
HKEY_CURRENT_CONFIG / HKCC

OLD: The value to search for.
Wrap multiword strings with "".

NEW: The value which will replace OLD.
Wrap multiword strings with "".
If not supplied, it default to empty string
which means delete all occurence of OLD
in the registry.

'''
if __name__ == '__main__':
if len(sys.argv) < 3 or len(sys.argv) > 4:
print 'Invalid Number of Arguments'
help()
exit()

## Root Hive
try:
start = {
'HKCU' : 'HKEY_CURRENT_USER',
'HKLM' : 'HKEY_LOCAL_MACHINE',
'HKCR' : 'HKEY_CLASSES_ROOT',
'HKU' : 'HKEY_USERS',
'HKCC' : 'HKEY_CURRENT_CONFIG',
}[sys.argv[1].upper()]
except KeyError:
start = sys.argv[1].upper()
try:

startHandle = {
'HKEY_CURRENT_USER' : _winreg.HKEY_CURRENT_USER,
'HKEY_LOCAL_MACHINE' : _winreg.HKEY_LOCAL_MACHINE,
'HKEY_CLASSES_ROOT' : _winreg.HKEY_CLASSES_ROOT,
'HKEY_USERS' : _winreg.HKEY_USERS,
'HKEY_CURRENT_CONFIG' : _winreg.HKEY_CURRENT_CONFIG,
}[start]
except KeyError:
print >> sys.stderr, 'Invalid Hive'
help()
exit()

## The substring to be replaced
old = sys.argv[2]

## The replacement string
try:
new = sys.argv[3]
except:
new = ''
main(start, startHandle, old, new)
if AccessError:
print '''
Some keys cannot be changed because you don't have the appropriate
permission to modify those keys, please try again with a suitable
user account.
'''
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top