'''
Win Registry module
(_winreg wrapper)
'''
import _winreg as reg
# convenience dicts
vTyp={
reg.REG_BINARY : 'BIN',
reg.REG_DWORD : 'DW',
reg.REG_DWORD_BIG_ENDIAN : 'DWB',
reg.REG_DWORD_LITTLE_ENDIAN : 'DWL',
reg.REG_EXPAND_SZ : 'XSZ',
reg.REG_LINK : 'LNK',
reg.REG_MULTI_SZ : 'MSZ',
reg.REG_RESOURCE_LIST : 'RES',
reg.REG_SZ : 'STR',
reg.REG_NONE : 'NUL',
}
rTyp=dict((v, k) for k, v in vTyp.items())
indent='\t' # the string used for indented output
class Val(object):
# Registry Value
def __init__(self, key, name, val, typ):
self.key, self.name, self.val, self.typ = key, name, val, typ
@property
def indented(self):
return '%s%s' % (indent*(self.key.level+1), self.__str__())
def __str__(self):
val=' - bin -' if self.typ==rTyp['BIN'] else self.val
return '%s : %s' % (self.name, val)
class Key(object):
# Registry Key
def __init__(self, parent, name):
self.parent, self.name = parent, name
self.level=parent.level+1
# ! ! ! opens keys in read/write mode ! ! !
self.wrk=reg.OpenKey(parent.wrk, self.name, 0, reg.KEY_ALL_ACCESS)
self._keys = self._vals = None
@property
def keys(self):
# returns a dict of subkeys
if not self._keys:
self._keys={}
for i in xrange(reg.QueryInfoKey(self.wrk)[0]):
name=reg.EnumKey(self.wrk, i).lower()
try:
self._keys[name]=Key(self, name)
except WindowsError: pass
return self._keys
@property
def vals(self):
# returns the list of values
if not self._vals:
self._vals=[]
for i in xrange(reg.QueryInfoKey(self.wrk)[1]):
try:
self._vals.append(Val(self, *reg.EnumValue(self.wrk, i)))
except WindowsError: pass
return self._vals
def __call__(self, path):
# access to a key
path=path.lower()
key=self
for p in path.split('/'):
key=key.keys[p]
return key
def __str__(self):
return '%s%s/' % (self.parent.__str__(), self.name)
@property
def indented(self):
return '%s%s' % (indent*self.level, self.name)
def walk(self):
# walk thru the subkeys tree
for key in self.keys.itervalues():
yield key
for k in key.walk():
yield k
def grep(self, text, kv='both', typ=(rTyp['STR'],)):
# searching keys and/or values for some text
for k in self.walk():
if kv in ('keys', 'both') and text in k.name:
yield k, None
if kv in ('vals', 'both'):
for v in k.vals:
if (v.typ in typ) and (text in v.val):
yield k, v
def grep2(self, text, kv='both', typ=(rTyp['STR'],)):
# a grep variant, might be more convinient in some cases
kb=None
for k in self.walk():
if kv in ('keys', 'both') and text in k.name:
if kv=='both':
yield k, False
kb=k
else:
yield k
if kv in ('vals', 'both'):
for v in k.vals:
if (v.typ in typ) and (text in v.val):
if kv=='both':
if k!=kb:
yield k, False
kb=k
yield v, True
else:
yield v
def create(self, path):
# create a subkey, and the path to it if necessary
k=self
for p in path.split('/'):
if p in k.keys:
k=k.keys[p]
else:
reg.CreateKey(k.wrk, p)
k=Key(k, p)
return k
def setVal(self, name, val, typ='str'):
# set value
typ=typ.upper()
if typ=='DW': typ='DWL'
typ=rTyp[typ]
reg.SetValueEx(self.wrk, name, 0, typ, val)
class Hkey(Key):
# Registry HKey
def __init__(self, name):
self.parent=None
self.level=0
self.name=name
self.wrk=reg.ConnectRegistry(None, getattr(reg, name))
self._keys=None
self._vals=None
def __str__(self):
return '/%s/' % self.name
class Root(Key):
# Registry Root
def __init__(self):
self.hkey={}
for key in (k for k in dir(reg) if k.startswith('HKEY_')):
try:
chk = reg.ConnectRegistry(None, getattr(reg, key))
inf = reg.QueryInfoKey(chk)
reg.CloseKey(chk)
except WindowsError: pass # some keys may appear in _winreg but can't be reached
else:
hk = Hkey(key)
try:
chk=hk.keys
except WindowsError: pass # some keys can be accessed but not enumerated
else: # some keys work fine ...
name=key[5:].lower()
self.hkey[name]=hk # for iterating
setattr(self, name, hk) # for easy access
@property
def keys(self):
return self.hkey
root=Root() # we should need only one Root per application, so let's instanciate it here.
if __name__=='__main__':
try:
print '\n---- Keys names -----\n'
for k in root.local_machine('software/python/pythoncore/2.5').keys: print k
print '\n---- Keys full paths -----\n'
for k in root.local_machine('software/python/pythoncore/2.5').keys.itervalues(): print k
print '\n---- SubTree walking -----\n'
for k in root.local_machine('software/python').walk(): print k
print '\n---- More readable -----\n'
for k in root.local_machine('software/python').walk():
print k.indented
for v in k.vals:
print '%s (- %s -) ' % (v.indented, vTyp[v.typ])
print '\n---- Searching the whole registry -----\n' # or at least what you have access to
for k in root.walk():
if 'interpreter' in k.name:
print k
for v in k.vals:
print '\t', v
for sk in k.walk():
print sk
for sv in sk.vals:
print '\t', sv
print '\n---- Looking for a string -----\n'
kb=None
for k, v in root.current_user.grep('python'):
if v:
if k!=kb:
print k
kb=k
print '\t', v
else:
print k
kb=k
print '\n---- Same thing, the other way -----\n'
for i, isval in root.current_user.grep2('python'):
print '\t%s'%i if isval else i
print '\n---- Gathering some stats -----\n'
from collections import defaultdict
kv=defaultdict(int)
for k in root.walk():
for v in k.vals:
kv[vTyp.get(v.typ, v.typ)]+=1
for k, v in sorted(kv.items()):
print '%s\t%10i' % (k, v)
print '\nTotal\t%10i' % sum(kv.values())
print '\n---- Creating some keys and values -----\n'
print root.current_user.create('p/y/t/h/o/n')
root.current_user('software').create('python').setVal('BDFL', 'Guido')
k=root.current_user('software/python')
k.setVal('ver', 3000, 'dw')
for v in k.vals:
print '%s (- %s -) ' % (v, vTyp[v.typ])
except UnicodeError: pass