_winreg module wrapper. Provides easy access, walking and creation/modification of keys and values. Tested with Win98 and XP (admin)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | '''
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
|
Caveats and limitations:
This module is meant to be simple so it doesn't deal with permissions neither does it provide any "delete" feature.
Neverthrless it does the job I need it for :
Creating keys, setting values, searching for keys or values.
Be carefull about the permission issue : The keys are opened in KEY_ALL_ACCESS mode ...
Delete Registry. Great code!
I wrote some code to delete a key and subkeys:
Getting: The Python service control handler failed. Traceback (most recent call last): File "win32serviceutil.pyc", line 802, in ServiceCtrlHandlerEx File "Service_usb.pyc", line 331, in SvcOtherEx AttributeError: 'Key' object has no attribute 'delete' %2: %3
When calling the delete... root.local_machine("SYSTEM").delete(r"CurrentControlSet\Services\mykey")