Une classe pour lire et écrire la registry d'un ordi local ou distant, avec gestions d'erreurs.
La partie principale de ce programme est la classe
RegistryRW.cls
Qui est indépendante du projet et peut être utilisée dans d'autres projets.
(le UserControl n'est que le test de la classe)
Utilisation:
Dim regRW As RegistryRW
Set regRW = New RegistryRW
Dim val As String
'Computername can be "" for local machine or a name of a computer on the network
val = regRW.GetRegValue("Computername", HKEY_CURRENT_USER, "Test1\test2\haha", "KeyName")
if regRW.ErrNumber <> 0 then
MsgBox regRW.ErrDescription
End If
'etc...
Source / Exemple :
Option Explicit
'RegistryRW.cls
'24.05.2010 Philippe Hollmuller (philippe.hollmuller@gmail.com)
'Class for reading writing windows registry with error managment.
'You are free to use this class in your applications but not to sell the source code
'Use:
'Dim regRW As RegistryRW
'Set regRW = New RegistryRW
'Dim val As String
''Computername can be "" for local machine or a name of a computer on the network
'val = regRW.GetRegValue("Computername", HKEY_CURRENT_USER, "Test1\test2\haha", "KeyName")
'if regRW.ErrNumber <> 0 then
' MsgBox regRW.ErrDescription
'End If
'Types Definition
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Public Enum RegKeyRootEnum
HKEY_CLASSES_ROOT = &H80000000
HKEY_CURRENT_USER = &H80000001
HKEY_LOCAL_MACHINE = &H80000002
HKEY_USERS = &H80000003
HKEY_CURRENT_CONFIG = &H80000005
End Enum
Public Enum RegValTypeEnum
REG_BINARY = 3
REG_DWORD = 4 'A DWORD is a 32-bit unsigned integer (range: 0 through 4294967295 decimal). Because a DWORD is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing.
REG_QWORD = 11 'A DWORD is a 64-bit unsigned integer (range: 0 through 18446744073709551615. Because a QWORD is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing.
REG_SZ = 1
REG_MULTI_SZ = 7
REG_EXPAND_SZ = 2
End Enum
'API Declarations
'pour fermer la connection à la base de registre distante
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, ByRef lpType As Long, ByVal lpData As String, ByRef lpcbData As Long) As Long
Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpData As String, ByVal cbData As Long) As Long
Private Declare Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey As Long, ByVal lpValueName As String) As Long
Private Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, ByVal samDesired As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, phkResult As Long, lpdwDisposition As Long) As Long
Private Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpSubKey As String) As Long
'pour se connecter à une base de regitre distante
Private Declare Function RegConnectRegistry Lib "advapi32.dll" Alias "RegConnectRegistryA" (ByVal lpMachineName As String, ByVal hKey As Long, phkResult As Long) As Long
'pour lister les sous-clé d'une ruche
Private Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long, ByVal lpReserved As Long, ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As Any) As Long
'pour lister les valeurs ruche
Private Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long
'ouvre une clé pour savoir si elle est valide
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
'Constants Definition
Private Const SYNCHRONIZE = &H100000
Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const KEY_QUERY_VALUE = &H1
Private Const KEY_SET_VALUE = &H2
Private Const KEY_CREATE_LINK = &H20
Private Const KEY_CREATE_SUB_KEY = &H4
Private Const KEY_ENUMERATE_SUB_KEYS = &H8
Private Const KEY_EVENT = &H1
Private Const KEY_NOTIFY = &H10
Private Const READ_CONTROL = &H20000
Private Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Private Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Private Const KEY_ALL_ACCESS = ((STANDARD_RIGHTS_ALL Or KEY_QUERY_VALUE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY Or KEY_CREATE_LINK) And (Not SYNCHRONIZE))
Private Const KEY_READ = ((STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY) And (Not SYNCHRONIZE))
Private Const KEY_EXECUTE = (KEY_READ)
Private Const KEY_WRITE = ((STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY) And (Not SYNCHRONIZE))
Private Const REG_CREATED_NEW_KEY = &H1
Private Const REG_DWORD_BIG_ENDIAN = 5
Private Const REG_DWORD_LITTLE_ENDIAN = 4
Private Const REG_FULL_RESOURCE_DESCRIPTOR = 9
Private Const REG_LINK = 6
Private Const REG_NONE = 0
Private Const REG_NOTIFY_CHANGE_ATTRIBUTES = &H2
Private Const REG_NOTIFY_CHANGE_LAST_SET = &H4
Private Const REG_NOTIFY_CHANGE_NAME = &H1
Private Const REG_NOTIFY_CHANGE_SECURITY = &H8
Private Const REG_OPTION_BACKUP_RESTORE = 4
Private Const REG_OPTION_CREATE_LINK = 2
Private Const REG_OPTION_NON_VOLATILE = 0
Private Const REG_OPTION_RESERVED = 0
Private Const REG_OPTION_VOLATILE = 1
Private Const REG_LEGAL_CHANGE_FILTER = (REG_NOTIFY_CHANGE_NAME Or REG_NOTIFY_CHANGE_ATTRIBUTES Or REG_NOTIFY_CHANGE_LAST_SET Or REG_NOTIFY_CHANGE_SECURITY)
Private Const REG_LEGAL_OPTION = (REG_OPTION_RESERVED Or REG_OPTION_NON_VOLATILE Or REG_OPTION_VOLATILE Or REG_OPTION_CREATE_LINK Or REG_OPTION_BACKUP_RESTORE)
Private Const BUFFER_SIZE As Long = 255
Private Const ERROR_NO_MORE_ITEMS = 259&
Private Const MILLION_1 As Double = 1000000 'To split big String numbers DWORD OR QWORD and make double buffering
'API call and Constants for transfomringt API error to string:
Private Declare Function FormatMessage Lib "kernel32" _
Alias "FormatMessageA" _
(ByVal dwFlags As Long, _
lpSource As Long, _
ByVal dwMessageId As Long, _
ByVal dwLanguageId As Long, _
ByVal lpBuffer As String, _
ByVal nSize As Long, _
Args As Any) As Long
Private Const MAX_PATH As Long = 260
Private Const LB_SETTABSTOPS As Long = &H192
Private Const FORMAT_MESSAGE_FROM_SYSTEM As Long = &H1000
Private Const FORMAT_MESSAGE_IGNORE_INSERTS As Long = &H200
Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK As Long = &HFF
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY As Long = &H2000
'Private attributes:
Private myErrNumber As Long
Private myErrDescription As String
'Properties
Public Property Get ErrNumber() As Long
ErrNumber = myErrNumber
End Property 'ok 22.05.2010
Public Property Get ErrDescription() As String
ErrDescription = myErrDescription
End Property 'ok 22.05.2010
'Functions
Public Function keyRootAsString(keyRoot As RegKeyRootEnum) As String
Select Case keyRoot
Case HKEY_CLASSES_ROOT
keyRootAsString = "HKEY_CLASSES_ROOT"
Case HKEY_CURRENT_CONFIG
keyRootAsString = "HKEY_CURRENT_CONFIG"
Case HKEY_CURRENT_USER
keyRootAsString = "HKEY_CURRENT_USER"
Case HKEY_LOCAL_MACHINE
keyRootAsString = "HKEY_LOCAL_MACHINE"
Case HKEY_USERS
keyRootAsString = "HKEY_USERS"
Case Else
keyRootAsString = CStrNotNull(keyRoot)
End Select
End Function 'ok 19.05.2010
Public Function keyRootFromString(keyRootStr As String) As RegKeyRootEnum
Select Case Trim(keyRootStr)
Case "HKEY_CLASSES_ROOT"
keyRootFromString = HKEY_CLASSES_ROOT
Case "HKEY_CURRENT_CONFIG"
keyRootFromString = HKEY_CURRENT_CONFIG
Case "HKEY_CURRENT_USER"
keyRootFromString = HKEY_CURRENT_USER
Case "HKEY_LOCAL_MACHINE"
keyRootFromString = HKEY_LOCAL_MACHINE
Case "HKEY_USERS"
keyRootFromString = HKEY_USERS
Case Else
keyRootFromString = 0
End Select
End Function 'ok 19.05.2010
Public Function valTypeAsString(valType As RegValTypeEnum) As String
Select Case valType
Case REG_BINARY
valTypeAsString = "REG_BINARY"
Case REG_DWORD
valTypeAsString = "REG_DWORD"
Case REG_QWORD
valTypeAsString = "REG_QWORD"
Case REG_SZ
valTypeAsString = "REG_SZ"
Case REG_MULTI_SZ
valTypeAsString = "REG_MULTI_SZ"
Case REG_EXPAND_SZ
valTypeAsString = "REG_EXPAND_SZ"
Case Else
valTypeAsString = CStrNotNull(valType)
End Select
End Function 'ok 23.05.2010
Public Function valTypeFromString(valTypeStr As String) As RegKeyRootEnum
Select Case Trim(valTypeStr)
Case "REG_BINARY"
valTypeFromString = REG_BINARY
Case "REG_DWORD"
valTypeFromString = REG_DWORD
Case "REG_QWORD"
valTypeFromString = REG_QWORD
Case "REG_SZ"
valTypeFromString = REG_SZ
Case "REG_MULTI_SZ"
valTypeFromString = REG_MULTI_SZ
Case "REG_EXPAND_SZ"
valTypeFromString = REG_EXPAND_SZ
Case Else
valTypeFromString = 0
End Select
End Function 'ok 19.05.2010
'private use to connect to a computer's registry, local computer if name is empty ""
Private Function connectRegistry(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
ByRef hKeyResult As Long, FunctionName As String, Path As String) As Boolean
On Error Resume Next
myErrNumber = 0
myErrDescription = ""
Dim rv As Long
rv = 1
rv = RegConnectRegistry(ComputerName, CLng(keyRoot), hKeyResult)
'l'api renvoie 0 si la connexion a pu être établi (cela évite de faire un ping)
If rv = 0 Then
connectRegistry = True
Else
connectRegistry = False
myErrNumber = rv
myErrDescription = "RegistryRW." & FunctionName & ": connectRegistry \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & WinApiErrorAsString(rv)
End If
If Err.Number <> 0 Then
connectRegistry = False
myErrNumber = Err.Number
myErrDescription = "RegistryRW." & FunctionName & ": connectRegistry \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & Err.Description
End If
End Function 'ok 19.05.2010
Private Function openKey(hKeyResult As Long, Path As String, hKeyTmp As Long, keyRoot As RegKeyRootEnum, _
ComputerName As String, FunctionName As String) As Boolean
On Error Resume Next
Dim rv As Long
rv = 1
rv = RegOpenKey(hKeyResult, Path, hKeyTmp)
'l'api renvoie 0 si la connexion a pu être établi (cela évite de faire un ping)
If rv = 0 Then
openKey = True
Else
openKey = False
myErrNumber = rv
myErrDescription = "RegistryRW." & FunctionName & ": Registry OpenKey \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & WinApiErrorAsString(rv)
End If
If Err.Number <> 0 Then
openKey = False
myErrNumber = Err.Number
myErrDescription = "RegistryRW." & FunctionName & ": Registry OpenKey \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & Err.Description
End If
End Function 'ok 19.05.2010
'Fonctions
'Delete e Registry Key with all his contained Values
Public Function DeleteRegistryKey(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String) As Boolean
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "DeleteRegistryKey", Path) Then
Dim hKeyTmp As Long
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "DeleteRegistryKey") Then
On Error Resume Next
RegCloseKey hKeyTmp 'close the key opened by openKey
Dim rv As Long
rv = RegDeleteKey(hKeyResult, Path)
If rv = 0 Then
DeleteRegistryKey = True
Else
DeleteRegistryKey = False
myErrNumber = rv
myErrDescription = "RegistryRW.DeleteRegistryKey \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & WinApiErrorAsString(rv)
End If
If Err.Number <> 0 Then
DeleteRegistryKey = False
myErrNumber = Err.Number
myErrDescription = "RegistryRW.DeleteRegistryKey \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & Err.Description
End If
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
End Function 'ok 19.05.2010
'Delete a Value from the Registry
Public Function DeleteValue(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String, ValueName As String) As Boolean
'le lien avec l'ordi distant ce fait grâce au hKeyResult qui est un paramettre de résultat
'hKeyResult est le dernier paramettre de RegConnectRegistry et le premier de RegOpenKey
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "DeleteValue", Path) Then
Dim hKeyTmp As Long
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "DeleteValue") Then
On Error Resume Next
Dim rv As Long
rv = RegDeleteValue(hKeyTmp, ValueName)
If rv = 0 Then
DeleteValue = True
Else
DeleteValue = False
myErrNumber = rv
myErrDescription = "RegistryRW.DeleteValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & WinApiErrorAsString(rv)
End If
If Err.Number <> 0 Then
DeleteValue = False
myErrNumber = Err.Number
myErrDescription = "RegistryRW.DeleteValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & Err.Description
End If
RegCloseKey hKeyTmp 'close the key opened by openKey
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
End Function 'ok 19.05.2010
'Creates a New Registry Key
Public Function CreateRegistryKey(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String) As Boolean
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "CreateRegistryKey", Path) Then
On Error Resume Next
Dim hKeyTmp As Long
Dim y As SECURITY_ATTRIBUTES
Dim Operation As Long
Dim rv As Long
rv = RegCreateKeyEx(hKeyResult, Path, 0, "", 0, KEY_ALL_ACCESS, y, hKeyTmp, Operation)
If rv = 0 Then
CreateRegistryKey = True
Else
CreateRegistryKey = False
myErrNumber = rv
myErrDescription = "RegistryRW.CreateRegistryKey \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & WinApiErrorAsString(rv)
End If
If Err.Number <> 0 Then
CreateRegistryKey = False
myErrNumber = Err.Number
myErrDescription = "RegistryRW.CreateRegistryKey \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & Err.Description
End If
RegCloseKey hKeyTmp 'close the key opened by RegCreateKeyEx
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
End Function 'ok 19.05.2010
'Get a specific Registry Value (to access the Default Registry Key Value set ValueName parameter as "")
Public Function GetRegValType(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String, ValueName As String) As RegKeyRootEnum
Dim rv As RegValTypeEnum
GetRegValue ComputerName, keyRoot, Path, ValueName, rv
GetRegValType = rv
End Function 'ok 23.05.2010
'Get a specific Registry Value (to access the Default Registry Key Value set ValueName parameter as "")
Public Function GetRegValue(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String, ValueName As String, Optional ByRef valType As RegValTypeEnum = REG_SZ) As String
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "GetRegValue", Path) Then
Dim hKeyTmp As Long
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "GetRegValue") Then
On Error Resume Next
Dim keyValType As Long
Dim KeyValSize As Long
Dim KeyVal As String
Dim tmpVal As String
Dim i As Integer
Dim rv As Long
tmpVal = String(1024, 0)
KeyValSize = 1024
rv = RegQueryValueEx(hKeyTmp, ValueName, 0, keyValType, tmpVal, KeyValSize)
If rv = 0 Then
If KeyValSize > 0 Then
If (Asc(Mid(tmpVal, KeyValSize, 1)) = 0) Then
tmpVal = Left(tmpVal, KeyValSize - 1)
Else
tmpVal = Left(tmpVal, KeyValSize)
End If
Else
tmpVal = ""
End If
Select Case keyValType
Case REG_DWORD, REG_QWORD
Dim valMillionCount As Double 'pour double buffering valeur en cas de QWord et DWORD, non signés de 32 et 64 bits
Dim valLow As Double 'pour double buffering valeur en cas de QWord et DWORD, non signés de 32 et 64 bits
valLow = 0
For i = Len(tmpVal) To 1 Step -1
If valLow * 256 > 99999999# Then
Dim milc As Double
milc = Fix(valLow / MILLION_1)
valLow = valLow - (milc * MILLION_1)
valMillionCount = valMillionCount + milc
End If
valMillionCount = valMillionCount * 256
valLow = valLow * 256
valLow = valLow + Asc(Mid(tmpVal, i, 1))
Next i
milc = Fix(valLow / MILLION_1)
valLow = valLow - (milc * MILLION_1)
valMillionCount = valMillionCount + milc
Dim ErrMsg As String
'set KeyVal:
If Not DblToString(valLow, valMillionCount, KeyVal, ErrMsg) Then
myErrNumber = 1
myErrDescription = "RegistryRW.GetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: Error by transforming Values to string."
Else
valType = keyValType
End If
Case Else
KeyVal = tmpVal
valType = keyValType
End Select
Else
KeyVal = ""
myErrNumber = rv
myErrDescription = "RegistryRW.GetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & WinApiErrorAsString(rv)
End If
If Err.Number <> 0 Then
KeyVal = ""
myErrNumber = Err.Number
myErrDescription = "RegistryRW.GetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & Err.Description
End If
GetRegValue = KeyVal 'return value
RegCloseKey hKeyTmp 'close the key opened by openKey
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
End Function 'ok 22.05.2010
'Tests if a key exists by key path
Public Function ExistsKey(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String) As Boolean
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "ExistsKey", Path) Then
Dim hKeyTmp As Long
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "ExistsKey") Then
ExistsKey = True
RegCloseKey hKeyTmp 'close the key opened by openKey
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
End Function 'ok 24.05.2010
'Tests if a Value name exists in the key path
Public Function ExistsValue(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String, ValueName As String) As Boolean
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "ExistsValue", Path) Then
Dim hKeyTmp As Long
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "ExistsValue") Then
On Error Resume Next
Dim keyValType As Long
Dim KeyValSize As Long
Dim tmpVal As String
tmpVal = String(1024, 0)
KeyValSize = 1024
If RegQueryValueEx(hKeyTmp, ValueName, 0, keyValType, tmpVal, KeyValSize) = 0 Then
ExistsValue = True
End If
RegCloseKey hKeyTmp 'close the key opened by openKey
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
End Function 'ok 24.05.2010
'Create or Modify a Registry Value (to access the Default Registry Key Value set ValueName parameter as "")
Public Function SetRegValue(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String, ValueName As String, NewValue As String, _
Optional ByVal RegValType As RegValTypeEnum = REG_SZ, _
Optional ByVal overwriteExixtingRegValType As Boolean = True) As Boolean
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "SetRegValue", Path) Then
Dim hKeyTmp As Long
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "SetRegValue") Then
On Error Resume Next
Dim rv As Long
Dim i As Integer
Dim valMillionCount As Double 'pour double buffering valeur en cas de QWord et DWORD, non signés de 32 et 64 bits
Dim valLow As Double 'pour double buffering valeur en cas de QWord et DWORD, non signés de 32 et 64 bits
Dim keyValType As Long
Dim KeyValSize As Long
Dim oldRegValType As Long
Dim tmpVal As String
tmpVal = String(1024, 0)
KeyValSize = 1024
Dim existingVal As Boolean
rv = RegQueryValueEx(hKeyTmp, ValueName, 0, keyValType, tmpVal, KeyValSize)
oldRegValType = keyValType 'pour pouvoir récrire l'ancienne valeur en cas d'échec dépassement de capacité
Select Case rv
Case 0
existingVal = True
Case 2
existingVal = False
keyValType = RegValType 'la valeur n'existe pas encore dans la registry
Case Else 'Error
SetRegValue = False
myErrNumber = rv
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & WinApiErrorAsString(rv)
RegCloseKey hKeyTmp 'close the key opened by openKey
RegCloseKey hKeyResult 'close the key opened by connectRegistry
Exit Function 'EXIT
End Select
If keyValType <> RegValType Then 'Différence entre existante dans la registry et
'voulue par la fonction
If overwriteExixtingRegValType Then
keyValType = RegValType
Else
SetRegValue = False
myErrNumber = rv
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: RegistryValue allready existing with a different type."
RegCloseKey hKeyTmp 'close the key opened by openKey
RegCloseKey hKeyResult 'close the key opened by connectRegistry
Exit Function 'EXIT
End If
End If
'Now do the writing depending on keyValType:
Select Case keyValType
Case REG_BINARY, REG_SZ, REG_MULTI_SZ, REG_EXPAND_SZ
tmpVal = NewValue
Case REG_DWORD, REG_QWORD
Dim oldVal As String 'lire Valeur existante, err et errDesc pour pouvoir revenir en arrière en cas de dépassement de capacité.?
Dim oldErrDescription As String
Dim oldErrNr As Long
If existingVal Then
oldErrNr = ErrNumber
oldErrDescription = ErrDescription
oldVal = Me.GetRegValue(ComputerName, keyRoot, Path, ValueName) 'lire valeur avant d'écrire pour pouvoir revenir en arrière en cas de dépassement de capacité
If Me.ErrNumber <> 0 Then
existingVal = False
End If
myErrNumber = oldErrNr
myErrDescription = oldErrDescription
End If
'préparation valeurs écriture
Dim ErrMsg As String
If Not setDWordQWordValueFromString(NewValue, valLow, valMillionCount, ErrMsg) Then
SetRegValue = False
myErrNumber = 1
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & NewValue & " is not " & IIf(keyValType = REG_DWORD, "DWORD", "QWORD") & ". " & ErrMsg
RegCloseKey hKeyTmp 'close the key opened by openKey
RegCloseKey hKeyResult 'close the key opened by connectRegistry
Exit Function 'EXIT
End If
tmpVal = ""
Dim loopLimit As Integer
If keyValType = REG_DWORD Then
loopLimit = 3
ElseIf keyValType = REG_QWORD Then
loopLimit = 7
End If
'Construct the string for RegSetValueEx DWORD or QWORD
For i = 0 To loopLimit
valLow = valLow + ((valMillionCount - (Fix(valMillionCount / 256) * 256)) * MILLION_1)
valMillionCount = Fix(valMillionCount / 256)
tmpVal = tmpVal & Chr(valLow - (Fix(valLow / 256) * 256))
valLow = Fix(valLow / 256)
Next
If valLow > 0 Or valMillionCount > 0 Then
SetRegValue = False
myErrNumber = 1
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & NewValue & " is not " & IIf(keyValType = REG_DWORD, "DWORD", "QWORD") & ", overflow." & ErrMsg
RegCloseKey hKeyTmp 'close the key opened by openKey
RegCloseKey hKeyResult 'close the key opened by connectRegistry
Exit Function 'EXIT
End If
Case Else 'keyValType not implemented for write
SetRegValue = False
myErrNumber = 1
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: keyValType " & CStr(keyValType) & " not implemented existing in registry. To be implemented in RegistryRW."
RegCloseKey hKeyTmp 'close the key opened by openKey
RegCloseKey hKeyResult 'close the key opened by connectRegistry
Exit Function 'EXIT
End Select
KeyValSize = Len(tmpVal)
'Ecriture
rv = RegSetValueEx(hKeyTmp, ValueName, 0, keyValType, tmpVal, KeyValSize)
If rv = 0 Then
Select Case keyValType 'Relecture pour contrôle
Case REG_DWORD, REG_QWORD
'dépassement de capacité, valeur écrite correspond à valeur voulue??
Dim valInRegEqualsWantedVal As Boolean
oldErrNr = ErrNumber
oldErrDescription = ErrDescription
Dim valLow1 As Double, valMillionCount1 As Double
Dim val1 As String
val1 = Me.GetRegValue(ComputerName, keyRoot, Path, ValueName) 'Lire la valeur écrite auparavant
If Me.ErrNumber <> 0 Then
SetRegValue = False
myErrDescription = "RegistryRW.SetRegValue read again: " & myErrDescription
RegCloseKey hKeyTmp 'close the key opened by openKey
RegCloseKey hKeyResult 'close the key opened by connectRegistry
Exit Function 'EXIT
End If
myErrNumber = oldErrNr
myErrDescription = oldErrDescription
If setDWordQWordValueFromString(NewValue, valLow, valMillionCount, ErrMsg) Then
If setDWordQWordValueFromString(val1, valLow1, valMillionCount1, ErrMsg) Then
valInRegEqualsWantedVal = ((valLow = valLow1) And _
(valMillionCount = valMillionCount1))
End If
End If
If valInRegEqualsWantedVal Then
SetRegValue = True
Else
SetRegValue = False
If existingVal Then 'remettre l'ancienne valeur
Me.SetRegValue ComputerName, keyRoot, Path, ValueName, oldVal, oldRegValType, overwriteExixtingRegValType
Else 'effacer la valeur faussement enregistrée
Me.DeleteValue ComputerName, keyRoot, Path, ValueName
End If
myErrNumber = 1
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: overflow."
RegCloseKey hKeyTmp 'close the key opened by openKey
RegCloseKey hKeyResult 'close the key opened by connectRegistry
Exit Function 'EXIT
End If
Case Else 'setting a string value, no control necessary
SetRegValue = True
End Select
Else
SetRegValue = False
myErrNumber = rv
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & WinApiErrorAsString(rv)
End If
If Err.Number <> 0 Then
SetRegValue = False
myErrNumber = Err.Number
myErrDescription = "RegistryRW.SetRegValue \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & "\" & ValueName & " failed: " & Err.Description
End If
RegCloseKey hKeyTmp 'close the key opened by openKey
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
End Function 'ok 22.05.2010
'list the printers on a computer
Public Function listComputerPrinter(ComputerName As String) As Collection
Set listComputerPrinter = listKeysIn(ComputerName, HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Print\Printers")
End Function 'ok 19.05.2010
Public Function listKeysIn(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String) As Collection
Dim rv As Collection
Set rv = New Collection
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "listKeysIn", Path) Then
Dim hKeyTmp As Long, Cnt As Long, sName As String, ret As Long
Cnt = 0
ret = BUFFER_SIZE
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "listKeysIn") Then
On Error Resume Next
'crer un buffer
sName = Space(BUFFER_SIZE)
'énumaire les sous-clé
While RegEnumKeyEx(hKeyTmp, Cnt, sName, ret, ByVal 0&, vbNullString, ByVal 0&, ByVal 0&) <> ERROR_NO_MORE_ITEMS
'ajoute les sous clés
rv.Add (Left$(sName, ret))
'prepare pour la clé suivante
Cnt = Cnt + 1
sName = Space(BUFFER_SIZE)
ret = BUFFER_SIZE
Wend
RegCloseKey hKeyTmp 'close the key opened by openKey
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
Set listKeysIn = rv
If Err.Number <> 0 Then
myErrNumber = Err.Number
myErrDescription = "RegistryRW.listKeysIn \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & Err.Description
End If
End Function 'ok 22.05.2010
Public Function listValuesIn(ComputerName As String, ByVal keyRoot As RegKeyRootEnum, _
Path As String) As Collection
Dim rv As Collection
Set rv = New Collection
Dim hKeyResult As Long
If connectRegistry(ComputerName, keyRoot, hKeyResult, "listValuesIn", Path) Then
Dim hKeyTmp As Long, Cnt As Long, sName As String, sData As String, ret As Long, RetData As Long
Cnt = 0
ret = BUFFER_SIZE
Cnt = 0
If openKey(hKeyResult, Path, hKeyTmp, keyRoot, ComputerName, "listValuesIn") Then
On Error Resume Next
sName = Space(BUFFER_SIZE)
sData = Space(BUFFER_SIZE)
ret = BUFFER_SIZE
RetData = BUFFER_SIZE
'enumerate the values
While RegEnumValue(hKeyTmp, Cnt, sName, ret, 0, ByVal 0&, ByVal sData, RetData) <> ERROR_NO_MORE_ITEMS
If ret > 0 Then
sName = Left$(sName, ret)
Else
sName = ""
End If
If RetData > 1 Then
sData = Left$(sData, RetData - 1)
Else
sData = ""
End If
If sName <> "" Then
rv.Add sName
End If
'prepare for next value
Cnt = Cnt + 1
sName = Space(BUFFER_SIZE)
sData = Space(BUFFER_SIZE)
ret = BUFFER_SIZE
RetData = BUFFER_SIZE
Wend
'Close the registry key
RegCloseKey hKeyTmp 'close the key opened by openKey
End If
RegCloseKey hKeyResult 'close the key opened by connectRegistry
End If
Set listValuesIn = rv
If Err.Number <> 0 Then
myErrNumber = Err.Number
myErrDescription = "RegistryRW.listValuesIn \\" & ComputerName & "\" & keyRootAsString(keyRoot) & "\" & Path & " failed: " & Err.Description
End If
End Function
'set les valeurs valLow et valMillionCount en fonction de la string d'entrée
Private Function setDWordQWordValueFromString(s As String, _
valLow As Double, valMillionCount As Double, _
ErrMsg As String) As Boolean
On Error Resume Next
'Test si cast en Cdbl possible:
Dim d As Double
d = CDbl(Trim(s))
If Err.Number <> 0 Then
ErrMsg = Err.Description
setDWordQWordValueFromString = False
Exit Function 'EXIT ERROR
End If
If d < 0 Or Fix(d) <> d Then 'négatif ou contenand virgule
ErrMsg = "Value < 0 is not a WORD, Word is unsigned value."
setDWordQWordValueFromString = False
Exit Function 'EXIT ERROR
End If
valLow = d 'd can be set from a big string like 1.2E+15
valMillionCount = Fix(valLow / MILLION_1) 'split in buffers
valLow = valLow - (valMillionCount * MILLION_1)
setDWordQWordValueFromString = True
'si pas d'erreur, valLow contient la valeur s sous forme de double, ok si 1.7E17,
'mais arrondi en virgule flottante si grand nombre en string passé en paramètre
'dépassant 15 caractères formattés pour calculs sur dbl
'limite sans double buffering sans perdre de précision: 999999999999999
'RECHERCHE DE PRECISION:
'peut être que la string passée contient un grand nombre pour un QWord 64 bits, calculer
If WordStrToLowAndHighDbl(Trim(s), valLow, valMillionCount) Then
setDWordQWordValueFromString = True
End If
Err.Clear
End Function 'ok 22.05.2010
'Transformer un string en double
Private Function WordStrToLowAndHighDbl(s As String, valLow As Double, valMillionCount As Double) As Boolean
On Error Resume Next
Dim v As Integer
Dim i As Long
Dim sLow As String, sMillionCount As String
Dim numberMillion As Integer
numberMillion = Len(CStr(MILLION_1)) - 1
If Len(s) <= numberMillion Then
sLow = s
Else
sLow = Right(s, numberMillion)
sMillionCount = Left(s, Len(s) - Len(sLow))
End If
Dim sTmp As String
Dim rv As Double
Dim dLow As Double
Dim dMillionCount As Double
Dim lowIsSet As Boolean
Dim MillionCountIsSet As Boolean
'Calcule valLow:
sTmp = sLow
rv = 0
For i = 1 To Len(sTmp)
v = CInt(Mid(sTmp, i, 1)) 'can make error if 1.7E17 passed as parameter
rv = 10 * rv
rv = rv + CDbl(Mid(sTmp, i, 1))
If Err.Number <> 0 Then
Err.Clear
Exit Function 'EXIT ERROR
End If
Next i
If Len(sTmp) > 0 Then
dLow = rv
lowIsSet = True
End If
'Calcule valMillionCount:
sTmp = sMillionCount
rv = 0
For i = 1 To Len(sTmp)
v = CInt(Mid(sTmp, i, 1)) 'can make error if 1.7E17 passed as parameter
rv = 10 * rv
rv = rv + CDbl(Mid(sTmp, i, 1))
If Err.Number <> 0 Then
Err.Clear
Exit Function 'EXIT ERROR
End If
Next i
If Len(sTmp) > 0 Then
dMillionCount = rv
MillionCountIsSet = True
End If
If lowIsSet Then
valLow = dLow
If MillionCountIsSet Then
valMillionCount = dMillionCount
Else
valMillionCount = 0
End If
WordStrToLowAndHighDbl = True
End If
Err.Clear
End Function 'ok 22.05.2010
'transforme deux doubles représentant un nombre en un string de sortie
Private Function DblToString(valLow, valMillionCount, _
ByRef StringToSet As String, ByRef ErrMsg As String) As Boolean
On Error GoTo DblToString_Err
Dim d As Double
Dim deci As Double
Dim rv As String
d = valLow
While d >= 1
d = d / 10
deci = d - Fix(d)
d = Fix(d)
rv = Left(CStr(Round(deci * 10)), 1) & rv
Wend
If valMillionCount > 0 Then
Dim numberMillion As Integer
numberMillion = Len(CStr(MILLION_1)) - 1
While Len(rv) < numberMillion
rv = "0" & rv
Wend
End If
d = valMillionCount
While d >= 1
d = d / 10
deci = d - Fix(d)
d = Fix(d)
rv = Left(CStr(Round(deci * 10)), 1) & rv
Wend
If rv = "" Then
rv = 0
End If
StringToSet = rv
DblToString = True
Exit Function
DblToString_Err:
StringToSet = ""
ErrMsg = Err.Description
DblToString = False
Err.Clear
End Function 'ok 19.05.2010
Private Function CStrNotNull(val As Variant)
CStrNotNull = ""
On Error Resume Next
CStrNotNull = CStr(val)
If Err.Number <> 0 Then
CStrNotNull = ""
End If
End Function
'API error to string:
Public Function WinApiErrorAsString(msgID As Long) As String
Dim ret As Long
Dim sVal As String
Dim sCodes As String
Dim sBuff As String
sBuff = Space$(MAX_PATH)
ret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or _
FORMAT_MESSAGE_IGNORE_INSERTS Or _
FORMAT_MESSAGE_MAX_WIDTH_MASK, _
0&, msgID, 0&, _
sBuff, Len(sBuff), 0&)
sBuff = Left$(sBuff, ret)
'sCodes = msgID & vbTab & Hex(msgID) & vbTab
If ret Then
WinApiErrorAsString = sCodes & sBuff
Else
WinApiErrorAsString = sCodes & "(No such error)"
End If
End Function
Conclusion :
A utiliser pour écrire et lire la registry en VB.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.