387 lines
12 KiB
Python
387 lines
12 KiB
Python
"""
|
|
Windows registry support.
|
|
|
|
openKey( keyname )
|
|
open existing key object
|
|
|
|
>>> key=openKey( r"HKLM\HARDWARE\DESCRIPTION\System" )
|
|
|
|
createKey( keyname )
|
|
create a key if it doesn't already exist
|
|
|
|
>>> key=createKey( r"HKLM\SOFTWARE\Python\Test" )
|
|
|
|
deleteKey( keyname )
|
|
delete a key if it exists
|
|
Note: deleteKey may not be recursive on all platforms.
|
|
|
|
>>> key=deleteKey( r"HKLM\SOFTWARE\Python\Test" )
|
|
|
|
RemoteKey( machine, top_level_key ):
|
|
open a key on another machine.
|
|
You can use the returned key as a basis for opens, creates and deletes
|
|
on the other machine.
|
|
|
|
>>> key=RemoteKey( "somemachine", "HKLM" )
|
|
|
|
For information on the key API, open a key and look at its docstring.
|
|
|
|
|
|
"""
|
|
|
|
import _winreg
|
|
import sys
|
|
import exceptions
|
|
import array
|
|
from types import *
|
|
import string
|
|
|
|
class RegType:
|
|
"Represents one of the types that can go into the registry"
|
|
def __init__( self, msname, friendlyname ):
|
|
self.msname=msname
|
|
self.friendlyname=friendlyname
|
|
self.intval=getattr( _winreg, msname )
|
|
|
|
def __repr__( self ):
|
|
"Return a useful representation of the type object"
|
|
return "<RegType %d: %s %s>" % \
|
|
(self.intval, self.msname, self.friendlyname )
|
|
|
|
_typeConstants={
|
|
_winreg.REG_NONE:
|
|
RegType( "REG_NONE", "None" ),
|
|
_winreg.REG_SZ:
|
|
RegType( "REG_SZ", "String" ),
|
|
_winreg.REG_EXPAND_SZ:
|
|
RegType("REG_EXPAND_SZ", "Expandable Template String" ),
|
|
_winreg.REG_BINARY:
|
|
RegType("REG_BINARY", "Binary Data"),
|
|
_winreg.REG_DWORD :
|
|
RegType("REG_DWORD", "Integer" ),
|
|
# _winreg.REG_DWORD_LITTLE_ENDIAN :
|
|
# RegType("REG_DWORD_LITTLE_ENDIAN", "Integer"),
|
|
_winreg.REG_DWORD_BIG_ENDIAN :
|
|
RegType("REG_DWORD_BIG_ENDIAN", "Big Endian Integer"),
|
|
_winreg.REG_LINK :
|
|
RegType("REG_LINK", "Link"),
|
|
_winreg.REG_MULTI_SZ :
|
|
RegType("REG_MULTI_SZ", "List of Strings"),
|
|
_winreg.REG_RESOURCE_LIST :
|
|
RegType("REG_RESOURCE_LIST", "Resource List"),
|
|
_winreg.REG_FULL_RESOURCE_DESCRIPTOR :
|
|
RegType( "REG_FULL_RESOURCE_DESCRIPTOR",
|
|
"Full Resource Descriptor" ),
|
|
_winreg.REG_RESOURCE_REQUIREMENTS_LIST:
|
|
RegType( "REG_RESOURCE_REQUIREMENTS_LIST",
|
|
"Resource Requirements List" )
|
|
}
|
|
|
|
regtypes={}
|
|
for constant in _typeConstants.values():
|
|
regtypes[constant.msname]=constant
|
|
|
|
class _DictBase:
|
|
"Base class for dictionary-type objects"
|
|
def __init__( self, key ):
|
|
self.key=key
|
|
|
|
def clear( self ):
|
|
"Clear the list of keys/data values, as in dictionaries"
|
|
keys=list( self.keys() )
|
|
map( self.__delitem__, keys )
|
|
|
|
def get( self, item, defaultVal=None ):
|
|
"Get a key/value by name or index"
|
|
try:
|
|
return self.__getitem__( item )
|
|
except (IndexError, EnvironmentError, WindowsError):
|
|
return defaultVal
|
|
|
|
def has_key( self, item ):
|
|
"Check if a key/data value with a particular name exists"
|
|
try:
|
|
self.__getitem__( item )
|
|
return 1
|
|
except (IndexError, EnvironmentError, WindowsError):
|
|
return 0
|
|
|
|
def keys( self ):
|
|
"Get a list of key/data value names"
|
|
keys=[]
|
|
try:
|
|
for i in xrange( 0, sys.maxint ):
|
|
keyname = self._nameFromNum( i )
|
|
keys.append( keyname )
|
|
except (IndexError, EnvironmentError, WindowsError):
|
|
pass
|
|
return keys
|
|
|
|
def values( self ):
|
|
"Get a list of key objects or data values"
|
|
values=[] # map() doesn't use the IndexError semantics...
|
|
for i in self:
|
|
values.append( i )
|
|
return values
|
|
|
|
def items( self ):
|
|
"Get pairs of keyname/key object or valuename/value data"
|
|
return map( None, self.keys(), self.values() )
|
|
|
|
def __len__( self ):
|
|
return len( self.keys() )
|
|
|
|
def _getName( item, nameFromNum ):
|
|
"Helper function -- don't use it directly"
|
|
if type( item ) == IntType:
|
|
try:
|
|
keyname = nameFromNum( item )
|
|
except (WindowsError, EnvironmentError):
|
|
raise IndexError, item
|
|
|
|
elif type( item ) in [StringType, UnicodeType]:
|
|
keyname=item
|
|
else:
|
|
raise exceptions.TypeError, \
|
|
"Requires integer index or string key name"
|
|
return keyname
|
|
|
|
|
|
class RegValuesDict( _DictBase ):
|
|
"A dictionary of registry data values"
|
|
def _nameFromNum( self, i ):
|
|
return self.key._nameFromNum( i )
|
|
|
|
def __getitem__( self, item ):
|
|
return self.key.getValueNameDataAndType( item )
|
|
|
|
def __setitem__( self, name, val):
|
|
if type( val )==TupleType:
|
|
data, datatype=val
|
|
assert isinstance( datatype, RegType )
|
|
self.key.setValue( name, data, datatype )
|
|
else:
|
|
self.key.setValue( name, val )
|
|
|
|
def __delitem__( self, item ):
|
|
valname=_getName( item, self._nameFromNum )
|
|
self.key.deleteValue( valname )
|
|
|
|
class RegKeysDict( _DictBase ):
|
|
"A dictionary of registry keys"
|
|
def _nameFromNum( self, item ):
|
|
return _winreg.EnumKey( self.key.handle, item )
|
|
|
|
def __getitem__( self, item ):
|
|
keyname=_getName( item, self._nameFromNum )
|
|
return self.key.openSubkey( keyname )
|
|
|
|
def __delitem__( self, item ):
|
|
keyname=_getName( item, self._nameFromNum )
|
|
self.key.deleteSubkey( keyname )
|
|
|
|
def openKey( keyname, samFlags=None ):
|
|
"Open a key by name"
|
|
lst=string.split( keyname, "\\", 1 )
|
|
if len( lst )==2:
|
|
hivename,path=lst
|
|
return hives[hivename].openSubkey( path )
|
|
else:
|
|
hivename=lst[0]
|
|
return hives[hivename]
|
|
|
|
def createKey( keyname ):
|
|
lst=string.split( keyname, "\\", 1 )
|
|
assert len( lst )==2
|
|
hivename,path=lst
|
|
return hives[hivename].createSubkey( path )
|
|
|
|
def deleteKey( keyname ):
|
|
lst=string.split( keyname, "\\", 1 )
|
|
assert len( lst )==2
|
|
hivename,path=lst
|
|
return hives[hivename].deleteSubkey( path )
|
|
|
|
|
|
class RegKey:
|
|
"A registry key object"
|
|
|
|
def __init__( self, name, handle=None ):
|
|
self.name=name
|
|
self.handle=handle
|
|
|
|
def _nameFromNum( self, item ):
|
|
"internal"
|
|
(name,data,datatype)=_winreg.EnumValue( self.handle, item )
|
|
return name
|
|
|
|
def __nonzero__(self):
|
|
"Is the key open?"
|
|
if self.handle:
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
def __cmp__ (self, other ):
|
|
"Compare two keys for equality"
|
|
if hasattr( other, "handle" ) and hasattr( other, "name" ):
|
|
return cmp( self.name, other.name )
|
|
else:
|
|
return cmp( self.handle, other )
|
|
|
|
def __repr__( self ):
|
|
return "<Windows RegKey: %s>"% self.name
|
|
|
|
def close(self ):
|
|
"Close the key"
|
|
return _winreg.CloseKey( self.handle )
|
|
|
|
def getSubkeyNames( self ):
|
|
"Get a list of subkey names"
|
|
return self.getSubkeys().keys()
|
|
|
|
def getValueNames( self ):
|
|
"Get a list of value names"
|
|
return self.getValues().keys()
|
|
|
|
def deleteSubkey( self, subkey ):
|
|
"Delete a subkey by name"
|
|
return _winreg.DeleteKey( self.handle, subkey )
|
|
|
|
def deleteValue( self, valname ):
|
|
"Delete a value by name"
|
|
return _winreg.DeleteValue( self.handle, valname )
|
|
|
|
def createSubkey( self, keyname ):
|
|
"Create a subkey by name"
|
|
handle=_winreg.CreateKey( self.handle, keyname )
|
|
return RegKey( self.name+"\\"+keyname, handle)
|
|
|
|
def openSubkey( self, keyname, samFlags=None ):
|
|
"Open a named subkey"
|
|
if samFlags:
|
|
handle=_winreg.OpenKey( self.handle, keyname, 0, samFlags )
|
|
else:
|
|
handle=_winreg.OpenKey( self.handle, keyname, 0 )
|
|
return RegKey( self.name+"\\"+keyname, handle )
|
|
|
|
def getSubkeys( self ):
|
|
"Get a dictionary-like mapping of subkeys"
|
|
return RegKeysDict( self )
|
|
|
|
def getValues( self ):
|
|
"Get a dictionary-like mapping of data values"
|
|
return RegValuesDict( self )
|
|
|
|
def getValueNameDataAndType( self, valname ):
|
|
"Get a data value's name, data and type all at one time"
|
|
try:
|
|
if type( valname )==IntType:
|
|
(valname,data,datatype)=_winreg.EnumValue( self.handle, valname )
|
|
else:
|
|
keyname=_getName( valname, self._nameFromNum )
|
|
(data,datatype)=_winreg.QueryValueEx( self.handle, keyname )
|
|
except (WindowsError, EnvironmentError):
|
|
raise IndexError, valname
|
|
|
|
if datatype==_winreg.REG_BINARY:
|
|
# use arrays for binary data
|
|
data=array.array( 'c', data )
|
|
|
|
return (valname, data, _typeConstants[datatype] )
|
|
|
|
def getValueData( self, valname ):
|
|
"Get a data value's data."
|
|
name, data, type=self.getValueNameDataAndType( valname )
|
|
return data
|
|
|
|
def setValue( self, valname, data, regtype=None ):
|
|
"Set a data value's data (and optionally type)"
|
|
if regtype:
|
|
typeint=regtype.intval
|
|
else:
|
|
if type( data ) in [StringType, UnicodeType]:
|
|
typeint=_winreg.REG_SZ
|
|
elif type( data )==ListType:
|
|
# XXX - _winreg currently only supports lists
|
|
# Also, probably should check each element is
|
|
# string/unicode.
|
|
typeint = _winreg.REG_MULTI_SZ
|
|
elif type( data )==IntType:
|
|
typeint=_winreg.REG_DWORD
|
|
elif type( data )==array.ArrayType:
|
|
typeint=_winreg.REG_BINARY
|
|
_winreg.SetValueEx( self.handle, valname, 0, typeint, data )
|
|
|
|
def flush(self ):
|
|
"Make sure that all changes are written to the registry. "
|
|
"Only use this if you know what you are doing. "
|
|
"It isn't usually needed."
|
|
_winreg.FlushKey( self.keyobbj )
|
|
|
|
def save( self, filename ):
|
|
"Save a key to a filename"
|
|
_winreg.SaveKey( self.keyobj, filename )
|
|
|
|
def load( self, subkey, filename ):
|
|
"Load a key from a filename"
|
|
return _winreg.RegLoadKey( self.handle, subkey, filename )
|
|
|
|
|
|
class RemoteKey( RegKey ):
|
|
"Open a key on a remote machine"
|
|
def __init__( self, machine, topLevelKey ):
|
|
assert topLevelKey in _hivenames
|
|
self.handle = _winreg.ConnectRegistry( machine, parentKey )
|
|
self.name=r"\\%s\%s" % (machine, topLevelKey )
|
|
|
|
_hivenames = ["HKEY_CLASSES_ROOT","HKEY_CURRENT_USER","HKEY_LOCAL_MACHINE",
|
|
"HKEY_USERS","HKEY_CURRENT_CONFIG","HKEY_DYN_DATA",
|
|
"HKEY_PERFORMANCE_DATA"]
|
|
hives={}
|
|
for name in _hivenames:
|
|
hives[name]=RegKey( name, getattr( _winreg, name ) )
|
|
hives["HKLM"]=hives["HKEY_LOCAL_MACHINE"]
|
|
hives["HKCR"]=hives["HKEY_CLASSES_ROOT"]
|
|
hives["HKCU"]=hives["HKEY_CURRENT_USER"]
|
|
|
|
_flagnames = ["KEY_ALL_ACCESS","KEY_CREATE_LINK", "KEY_CREATE_SUB_KEY",
|
|
"KEY_ENUMERATE_SUB_KEYS", "KEY_EXECUTE", "KEY_NOTIFY",
|
|
"KEY_QUERY_VALUE", "KEY_READ", "KEY_SET_VALUE"]
|
|
flags={}
|
|
for name in _flagnames:
|
|
flags[name]=getattr( _winreg, name )
|
|
|
|
_RegNotifyChangeKeyValueOptions=[ "REG_NOTIFY_CHANGE_ATTRIBUTES",
|
|
"REG_NOTIFY_CHANGE_SECURITY", "REG_NOTIFY_CHANGE_LAST_SET",
|
|
"REG_NOTIFY_CHANGE_NAME", "REG_LEGAL_CHANGE_FILTER" ]
|
|
|
|
_RegRestoreKeyOptions=["REG_WHOLE_HIVE_VOLATILE",
|
|
"REG_NO_LAZY_FLUSH",
|
|
"REG_OPTION_VOLATILE",
|
|
"REG_REFRESH_HIVE",
|
|
"REG_OPTION_NON_VOLATILE",
|
|
"REG_OPTION_BACKUP_RESTORE" ]
|
|
|
|
_RegCreateKeyExOptions=[
|
|
"REG_LEGAL_OPTION",
|
|
"REG_OPTION_RESERVED",
|
|
"REG_OPTION_VOLATILE",
|
|
"REG_OPTION_NON_VOLATILE",
|
|
"REG_OPTION_BACKUP_RESTORE",
|
|
"REG_CREATED_NEW_KEY",
|
|
"REG_OPENED_EXISTING_KEY",
|
|
"REG_OPTION_CREATE_LINK"]
|
|
|
|
|
|
#unusednames=_RegNotifyChangeKeyValueOptions+_RegRestoreKeyOptions+_RegCreateKeyExOptions
|
|
|
|
#typeConstantNames=map( lambda x: x.msname, typeConstants.values() )
|
|
|
|
#allnames=_hivenames+_flagnames+typeConstantNames+unusednames
|
|
#winregnames=_winreg.__dict__.keys()
|
|
#for name in winregnames:
|
|
# if name not in allnames:
|
|
# print name
|
|
|