Mailing List Archive

Some win32 registry functions (black, dangerous magic)
I often have the desire to create/modify registry entries which are not the
"default" entries, and until today I've always considered this stuff very
black magic (why two types of every function, why do I need to open a key,
yada, yada).

The following is a module which provides a few features beyond the
regutil.py package distributed with win32all...

1) You specify keys as single paths, not root-key+path
2) You can store non-int/non-string objects (pickled)
3) You can store named values with the same command as default
values
4) Has a "register python scripts as executables" function
(example, NT only)
5) Has an "add directory to system path" function (example, NT
only)

I'd appreciate it if the Windows gurus could take a look and point out
anything I've done which might scramble someone's registry. This is a
blatant rip-off of Mark Hammond's regutil.py .

Hereby released for whatever purpose, but at your own risk. No warranties
expressed, implied or scandalised.

8<____________________ regutilsex.py _____

import win32api, win32con, string, types

def _getDataType( data, coerce = 1 ):
'''
Return a tuple of dataType, data for a given object
automatically converts non-string-or-tuple-data into
strings by calling pickle.dumps
'''
if type( data ) is types.StringType:
return win32con.REG_SZ, data
elif type( data ) is types.IntType:
return win32con.REG_DWORD, data
# what about attempting to convert Longs, floats, etceteras to ints???
elif coerce:
import pickle
return win32con.REG_SZ, pickle.dumps( data )
else:
raise TypeError, '''Unsupported datatype for registry, use
getDataType( data, coerce=1) to store types other than string/int.'''

def _getBaseKey( fullPathSpec ):
'''
Split a "full path specification" registry key
into its root and subpath components
'''
key = ''
subkey = fullPathSpec
# while loop will strip off preceding \\ characters
while subkey and not key:
key, subkey = string.split( fullPathSpec, '\\', 1 )
try:
return getattr( win32con, key ), subkey
except AttributeError:
raise '''Unknown root key %s in registry path %s'''% (key,
fullPathSpec)

def RegSetValue( key, valuename='', data='', allowPickling=1 ):
'''
Set a registry value by providing a fully-specified
registry key (and an optional sub-key/value name),
and a data element. If allowPickling is true, the
data element can be any picklable element, otherwise
data element must be a string or integer.
'''
root, subkey = _getBaseKey( key )
dataType, data = _getDataType( data, allowPickling )
try:
hKey = win32api.RegOpenKeyEx( root , subkey, 0,
win32con.KEY_ALL_ACCESS) # could we use a lesser access model?
except:
hKey = win32api.RegCreateKey( root, subkey )
try:
if not valuename: # the default value
win32api.RegSetValue( hKey, valuename, dataType, data )
else: # named sub-value
win32api.RegSetValueEx( hKey, valuename, 0, dataType, data )
finally:
win32api.RegCloseKey( hKey)

def RegQueryValue( key, valuename='', pickling=0 ):
'''
Get a registry value by providing a fully-specified
registry key (and an optional sub-key/value name)
If pickling is true, the data element will be
unpickled before being returned.
'''
#print 'key', key
root, subkey = _getBaseKey( key )
if not valuename: # the default value
data, type = win32api.RegQueryValue( root , subkey)
else:
try:
#print root, subkey
hKey = win32api.RegOpenKeyEx( root, subkey, 0,
win32con.KEY_READ)
#print hKey, valuename
try:
data, type = win32api.RegQueryValueEx( hKey, valuename )
except: #
data, type = None, 0 # value is not available... should we
raise an error here instead???
pickling = None
finally:
win32api.RegCloseKey( hKey)
if pickling:
import pickle
data = pickle.loads( data )
return data


################## EXAMPLES FOLLOW
def AddPathEntry( newEntry, user = 1, prepend=0 ):
'''
Add or remove path entry on NT, use prepend == -1 for removal,
use prepend == 0 for append, prepend= 1 for prepending to the
current path.
'''
if user:
user = 'USER'
else:
user = 'MACHINE'
key, valuename = COMMON_KEYS[ (user, 'PATH') ]
_PathManager( key, valuename, newEntry, prepend )

def PyExecutables( user = 1, prepend=0 ):
'''
Register/Deregister Python files as executables
'''
if user:
user = 'USER'
else:
user = 'MACHINE'
key, valuename = COMMON_KEYS[ (user, 'PYEXECUTABLES') ]
# the default executables + Python scripts...
if prepend < 0: # are to eliminate only .py
newEntry = '.PY'
else:
newEntry = '.PY;.COM;.EXE;.BAT;.CMD'
_PathManager( key, valuename, newEntry, prepend )

def _PathManager( key, valuename, newEntry, prepend=0,
eliminate_duplicates=1 ):
'''
Create a new Path entry on NT machines (or kill an old one)
user determines whether to alter the USER or the Machine's path
prepend
1 -> add newEntry to start
0 -> add newEntry to end
-1 -> don't add newEntry
eliminate_duplicates determines whether to kill equal paths

All values are converted to lower case
'''
# get current value...
curval = RegQueryValue( key, valuename ) or ''
# split into elements
curval = string.split( string.lower(curval), ';' )
if type( newEntry ) not in (types.ListType, types.TupleType):
newEntry = string.split( string.lower(newEntry), ';' )
# eliminate duplicates of the newEntry
curval = map( None, curval) # strip out null entries
if eliminate_duplicates:
newval = []
for p in curval:
if p not in newEntry:
newval.append( p )
curval = newval
if prepend == 1:
curval = list(newEntry) + curval
elif prepend == 0:
curval = curval + list( newEntry )
elif prepend == -1: # this call is just killing the path entry
pass
#now do the recombination
curval = string.join( curval, ';' )
RegSetValue( key, valuename, curval )

# following constants seem to reflect where path data is stored on NT
machines
# no idea if it'll work on a 95 machine

COMMON_KEYS = {
('USER','PATH') : ('''HKEY_CURRENT_USER\\Environment''', 'path'),
('MACHINE','PATH') :
('''HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session
Manager\\Environment''', 'path'),
('USER','PYEXECUTABLES') : ('''HKEY_CURRENT_USER\\Environment''',
'pathext'),
('MACHINE','PYEXECUTABLES') :
('''HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session
Manager\\Environment''', 'pathext')
}

____________________________________________________
Mike C. Fletcher -- Virtual Environment Designer
mcfletch@vrtelecom.com
http://www.vrtelecom.com