OZORegistry.psm1
# CLASSES Class OZORegistryKey { # PROPERTIES: Booleans, Strings [Boolean] $Display = $false [Boolean] $keyExists = $true [Boolean] $keyPathValid = $true [Boolean] $namesRead = $true [String] $keyPath = $null # PROPERTIES: PSCustomObjects Hidden [PSCustomObject] $Key = $null Hidden [PSCustomObject] $Logger = $null # PROPERTIES: PSCustomObject Lists Hidden [System.Collections.Generic.List[PSCustomObject]] $Names = @() # METHODS: Constructor method OZORegistryKey([String]$KeyPath,[Boolean]$Display) { # Set properties $this.Display = $Display # Create a logger $this.Logger = (New-OZOLogger) # Determine if Display is false and if so disable Logger display If ($this.Display -eq $false) { $this.Logger.SetConsoleOutput("off") } # Call ValidateKeyPath to determine if KeyPath format is valid [and populate this.KeyPath] If ($this.ValidateKeyPath($KeyPath) -eq $true) { # Key is valid $this.Logger.Write(("Using key path " + $this.keyPath + "."),"Information") # Call ReadKey to set keyExists [and populate registryKey] If ($this.ReadKey() -eq $true) { # Retrieved key; call ReadKeyNames [and populate Names] If ($this.ReadKeyNames() -eq $true) { # Able to read all key names $this.Logger.Write(($this.keyPath + " exists and all names read."),"Information") # Display key for user-interactive sessions $this.DisplayKey() } Else { # No names found or unable to read all names; log $this.Logger.Write(($this.keyPath + " contains no names or some namues could not be read."),"Warning") $this.namesRead = $false } } Else { # Unable to retrieve key; log $this.Logger.Write(("Key `"" + $KeyPath + "`" could not be read."),"Error") $this.keyExists = $false $this.namesRead = $false } } Else { # Key format is not valid; log $this.Logger.Write(("Key `"" + $KeyPath + "`" is not a valid path."),"Error") $this.keyExists = $false $this.keyPathValid = $false $this.namesRead = $false } } # METHODS: Validate key path method Hidden [Boolean] ValidateKeyPath([String]$KeyPath) { # Control variable [Boolean] $Return = $true # Local variables [Array] $validShortStrings = @("HKCR:","HKCU:","HKLM:","HKU:","HKCC:") [Array] $validLongStrings = @("HKEY_CLASSES_ROOT","HKEY_CURRENT_USER","HKEY_LOCAL_MACHINE","HKEY_USERS","HKEY_CURRENT_CONFIG") [String] $keyPathStart = $null # Determine if KeyPath contains a \ character If ($KeyPath -Like "*\*") { # KeyPath contains a \ character; split the string on \ and store the first string as keyPathStart $keyPathStart = ($KeyPath -Split "\\" )[0] # Determine if the first string is found in valid*Strings If (($validShortStrings + $validLongStrings) -Contains $keyPathStart) { # First string appears in valid*Strings lists; determine if key is in validShortStrings If ($validShortStrings -Contains $keyPathStart) { # Key is in the short format; convert to long format and set this.keyPath $this.keyPath = ("Registry::" + (Convert-OZORegistryPath -RegistryPath $KeyPath)) } Else { # Key is in the long format; set this.keyPath $this.keyPath = ("Registry::" + $KeyPath) } } Else { # First string does not appear in valid*Strings $Return = $false } } Else { # Path does not contain a \ character $Return = $false } # return return $Return } # METHODS: Read key method Hidden [Boolean] ReadKey() { # Control variable [Boolean] $Return = $true # Determine that Key is valid and set If ($this.keyPathValid -eq $true -And $null -ne $this.keyPath) { # Key is valid and set; try to get the key Try { $this.Key = (Get-Item -Path $this.keyPath -ErrorAction Stop) # Success } Catch { # Failure $Return = $false } } Else { $Return = $false } # Return return $Return } # METHODS: Read key names method Hidden [Boolean] ReadKeyNames() { # Control variable [Boolean] $Return = $true # Determine that registryKey is populated If ($null -ne $this.Key) { # Registry key is populated; determine if it has no properties If ($this.Key.Property.Count -eq 0) { # There are no properties; nothing to do $Return = $false # Otherwise determine if the Property count is 1 and it's Name is "(default)" } ElseIf ($this.Key.ValueCount -eq 1 -And $this.Key.Property -Contains "(default)") { # Key contains only one property and it is the (default) property; nothing to do $Return = $false } Else { # Key contains one or more names that are not "(default)"; iterate through the names ForEach ($keyProperty in $this.Key.Property) { $this.Names.Add(([OZORegistryKeyName]::new($keyProperty,$this.Key.GetValue($keyProperty,$null,"DoNotExpandEnvironmentNames")))) } # Determine if the count of registry values does not match the number of objects in the Names list If ($this.Key.ValueCount -ne $this.Names.Count) { # The counts do not match (some name could not be represented with a RegistryKeyName object); clear Names $this.Names = @() $Return = $false } } } # Return return $Return } # METHODS: Set display method [Void] SetDisplay([Boolean]$DisplayBool) { # Determine if SetValue is true If ($DisplayBool -eq $true) { # SetValue is true $this.Display = $true } Else { # SetValue is false $this.Display = $false } } # METHODS: Display key method [Void] DisplayKey() { # Control variable [Boolean] $changesPending = $false # Determine if session is user-interactive If ((Get-OZOUserInteractive) -eq $true -And $this.Display -eq $true) { # Session is user-interactive and Display is True; determine if the counts do not match If ($this.Key.ValueCount -ne $this.Names.Count) { # Counts do not match; Names have been added or removed $changesPending = $true } # Iterate through the key properties ForEach ($Property in $this.Key.Property) { # Determine if the Name is found in Names If ($this.Names.Name -Contains $Property) { # Determine if the Key.Property value does not match the Name.Value If ($this.Key.GetValue($Property,$null,"DoNotExpandEnvironmentNames") -ne $this.ReturnKeyNameValue($Property)) { # Values do not match $changesPending = $true } } } # Display the key representation $this.Names | Select-Object -Property Name,Type,Value | Format-Table | Out-Host # Determine if any changes are pending If ($changesPending -eq $true) { "`r`nThere are pending changes. Use ProcessChanges() to apply these changes to the registry key." | Out-Host } } } # METHODS: Return registry key name value method [Object] ReturnKeyNameValue($Name) { # Local variables [PSCustomObject] $keyName = $null # Determine if the key path is valid If ($this.keyPathValid -eq $true) { # Key path is valid; determine if the key exists If ($this.keyExists -eq $true) { # Key exists; determine if the names were read If ($this.namesRead -eq $true) { # Names were read; determine if Names contains Name If ($this.Names.Name -Contains $Name) { # Get the specific Name as keyName $keyName = ($this.Names | Where-Object {$_.Name -eq $Name}) # Switch on Type and return the value as the corresponding type Switch ($keyName.Type.ToLower()) { "binary" { return [Byte[]] $keyName.Value } "dword" { return [Int32] $keyName.Value } "expandstring" { return [String] $keyName.Value } "multstring" { return [String[]] $keyName.Value } "qword" { return [Int64] $keyName.Value } "string" { return [String] $keyName.Value } default { return [String] "Unhandled type" } } } Else { # Name not found in Names.Name return "Name not found in Key" } } Else { # Could not read names return "Could not read key names" } } Else { # Key path does not exist return "Key not found" } } Else { # Key Path is not valid return "Key path is not valid" } #Return return "Unsupported" } # METHODS: Return registry key name type method [String] ReturnKeyNameType($Name) { # Determine if key is valid If ($this.keyPathValid -eq $true) { # Key path is valid; determine if the key exists If ($this.keyExists -eq $true) { # Key exists; determine if the names were read If ($this.namesRead -eq $true) { # Names were read; determine if Name exists in Names list If ($this.Names.Name -Contains $Name) { # Name exists in Names list; return the value as string return ($this.Names | Where-Object {$_.Name -eq $Name}).Type } } Else { # Could not read names return "Could not read key names" } } Else { # Key path does not exist return "Key not found" } } Else { # Key Path is not valid return "Key path is not valid" } # Return return "Unsupported" } # METHODS: Add key name method [Boolean] AddKeyName([String]$Name,$Value) { # Control variable [Boolean] $Return = $true # Determine if Name already exists in Names If ($this.Names.Name -Contains $Name) { # Names already contains Name $this.Logger.Write(("Key already contains a " + $Name + " name; skipping."),"Warning") $Return = $false } Else { # Names does not already contain this Name; add to list $this.Names.Add(([OZORegistryKeyName]::new($Name,$Value))) } # Display key values for user-interactive sessions $this.DisplayKey() # Return return $Return } # METHODS: Add key name method [Boolean] RemoveKeyName([String]$Name) { # Control variable [Boolean] $Return = $true # Determine if Name exists in Names If ($this.Names.Name -Contains $Name) { # Names contains Name; remove it $this.Names.Remove(($this.Names | Where-Object {$_.Name -eq $Name})) } Else { # Names does not contain Name; nothing to do $this.Logger.Write(("Key does not contain a " + $Name + " name; skipping."),"Warning") $Return = $false } # Display key values for user-interactive sessions $this.DisplayKey() # Return return $Return } # METHODS: Update key name method [Boolean] UpdateKeyName([String]$Name,$Value) { # Control variable [Boolean] $Return = $true # Determine if this Name exists in Names If ($this.Names.Name -Contains $Name) { # Namee exists; determine if types match If (($this.Names | Where-Object {$_.Name -eq $Name}).Value.GetType() -eq $Value.GetType()) { # Types match; update with new Value ($this.Names | Where-Object {$_.Name -eq $Name}).Value = $Value } Else { $this.Logger.Write("Types do not match; name will not be updated.","Warning") $Return = $false } } Else { # Value does not exist; add it $Return = ($this.AddKeyName([String]$Name,$Value)) } # Display key values for user-interactive sessions $this.DisplayKey() # Return return $Return } # METHODS: Process changes method [Boolean] ProcessChanges() { # Control variable [Boolean] $Return = $true # Determine that operator is local Administrator If ((Test-OZOLocalAdministrator) -eq $true) { # Operator is local Administrator; determine if key does not exist If ([Boolean](Test-Path -Path $this.keyPath -ErrorAction SilentlyContinue) -eq $false) { # Key does not exist; try to create it Try { New-Item -Path $this.keyPath -ErrorAction Stop # Success; iterate through Values ForEach ($Name in $this.Names) { # Try to create each value Try { New-ItemProperty -Path $this.keyPath -Name $Name.Name -Value $Name.Value -PropertyType $Name.Type -ErrorAction Stop # Success } Catch { # Failure $this.Logger.Write(("Error creating " + $Name.Name + " in " + $this.keyPath + "."),"Error") $Return = $false } } } Catch { # Failure $this.Logger.Write(("Failed to create registry key" + $this.keyPath + "."),"Error") $Return = $false } } Else { # The key already exists; perform the remove operation - iterate through the properties in Key ForEach ($Property in $this.Key.Property) { # Determine if the property is not found in Values.Name If ($this.Names.Name -NotContains $Property) { # Property is not found in Values.Name; try to delete it Try { Remove-ItemProperty -Path $this.keyPath -Name $Property -ErrorAction Stop # Success } Catch { # Failure $this.Logger.Write(("Failed to remove " + $Property + " from " + $this.keyPath + "."),"Error") $Return = $false } } } # Perform the update operation - iterate through the Names ForEach ($Name in $this.Names) { # Determine that Key.Property contains Name.Name If ($this.Key.Property -Contains $Name.Name) { # Key.Property contains Name.Name; determine that Name.Value is different from the Key.Property value If ($Name.Value -ne $this.Key.GetValue($Name.Name)) { # Name.Value and the Key.Property value do not match; determine if the types match If ($Name.Type -eq $this.Key.GetValueKind($Name.Name)) { # Types match; try to update Try { Set-ItemProperty -Path $this.keyPath -Name $Name.Name -Value $Name.Value # Success } Catch { # Failure $this.Logger.Write(("Unable to update " + $Name.Name + " in " + $this.keyPath + "."),"Error") $Return = $false } } Else { # Types do not match $this.Logger.Write(("Type mismatch when attempting to update " + $Name.Name + " in " + $this.keyPath + "."),"Error") $Return = $false } } } } # Perform the add operation - iterate through the Names in Value ForEach ($Name in $this.Names) { # Determine if the properties in Key do not contain Value If ($this.Key.Property -NotContains $Name.Name) { # Key does not contain Value; try to add it Try { New-ItemProperty -Path $this.keyPath -Name $Name.Name -Value $Name.Value -PropertyType $Name.Type -ErrorAction Stop # Success } Catch { # Failure $this.Logger.Write(("Failed to add " + $Name.Name + " to " + $this.keyPath),"Error") $Return = $false } } } } # Reread the key $this.ReadKey() } Else { # Operator is not local Administrator $this.Logger.Write("Writing registry keys requires Administrator privileges.","Error") $Return = $false } # Display the key for user-interactive sessions $this.DisplayKey() # Return return $Return } } Class OZORegistryKeyName { # PROPERTIES [String] $Name = $null [String] $Type = $null # METHODS: Constructor method [Binary] OZORegistryKeyName([String]$Name,[Byte[]]$Value) { # Set properties $this.Name = $Name $this.Type = "Binary" # Add and set Data property Add-Member -InputObject $this -MemberType NoteProperty -Name "Value" -TypeName "Byte[]" -Value $Value -Force } # METHODS: Constructor method [Dword] OZORegistryKeyName([String]$Name,[Int32]$Value) { # Set properties $this.Name = $Name $this.Type = "Dword" # Add and set Data property Add-Member -InputObject $this -MemberType NoteProperty -Name "Value" -TypeName "Int32" -Value $Value -Force } # METHODS: Constructor method [ExpandString|String] OZORegistryKeyName([String]$Name,[String]$Value) { # Set properties $this.Name = $Name # Determine if string contains a % character If ($Value -Like "*%*") { # Data contains a % $this.Type = "ExpandString" } Else { # Data does not contain a % character $this.Type = "String" } # Add the Data property with the correct type Add-Member -InputObject $this -MemberType NoteProperty -Name "Value" -TypeName "String" -Value $Value -Force } # METHODS: Constructor method [MultString] OZORegistryKeyName([String]$Name,[String[]]$Value) { # Set properties $this.Name = $Name $this.Type = "MultString" # Add and set Data property Add-Member -InputObject $this -MemberType NoteProperty -Name "Value" -TypeName "String[]" -Value $Value -Force } # METHODS: Constructor method [Qword] OZORegistryKeyName([String]$Name,[Int64]$Value) { # Set properties $this.Name = $Name $this.Type = "Qword" # Add and set Data property Add-Member -InputObject $this -MemberType NoteProperty -Name "Value" -TypeName "Int64" -Value $Value -Force } } # FUNCTIONS Function Convert-OZORegistryPath { <# .SYNOPSIS See description. .DESCRIPTION Converts a registry string from one format to another, e.g., "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion" to "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion". If the input string is invalid, it is returned unmodified. .PARAMETER RegistryPath The registry string to convert. Accepts pipeline input. .EXAMPLE Convert-OZORegistryPath -Path "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion" HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion .EXAMPLE Convert-OZORegistryPath -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion" HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion .EXAMPLE "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion" | Convert-OZORegistryPath HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion .LINK https://github.com/onezeroone-dev/OZORegistry-PowerShell-Module/blob/main/Documentation/Convert-OZORegistryPath.md #> # Parameters [CmdletBinding()] Param ( [Parameter(Mandatory=$true,HelpMessage="The registry path to convert")][String]$RegistryPath ) # Switch on RegistryPath Switch($RegistryPath) { {$_ -Like "HKCR:\*" } { return $RegistryPath.Replace("HKCR:","HKEY_CLASSES_ROOT") } {$_ -Like "HKCU:\*" } { return $RegistryPath.Replace("HKCU:","HKEY_CURRENT_USER") } {$_ -Like "HKLM:\*" } { return $RegistryPath.Replace("HKLM:","HKEY_LOCAL_MACHINE") } {$_ -Like "HKU:\*" } { return $RegistryPath.Replace("HKU:" ,"HKEY_USERS") } {$_ -Like "HKCC:\*" } { return $RegistryPath.Replace("HKCC:","HKEY_CURRENT_CONFIG") } {$_ -Like "HKEY_CLASSES_ROOT\*" } { return $RegistryPath.Replace("HKEY_CLASSES_ROOT","HKCR:") } {$_ -Like "HKEY_CURRENT_USER\*" } { return $RegistryPath.Replace("HKEY_CURRENT_USER","HKCU:") } {$_ -Like "HKEY_LOCAL_MACHINE\*" } { return $RegistryPath.Replace("HKEY_LOCAL_MACHINE","HKLM:") } {$_ -Like "HKEY_USERS\*" } { return $RegistryPath.Replace("HKEY_USERS","HKU:") } {$_ -Like "HKEY_CURRENT_CONFIG\*"} { return $RegistryPath.Replace("HKEY_CURRENT_CONFIG","HKCC:") } default { return $RegistryPath } } } Function Get-OZORegistryKey { <# .SYNOPSIS See description. .DESCRIPTION Returns an OZORegistryKey object that represents a registry key (whether existing or not). The object contains methods for reading, adding, updating, and removing key values; and a method for processing (writing) the changes to the registry. This function (and resulting object) is the most robust and flexible use of this module. .PARAMETER Key The registry key in the short ("HKLM:\...") or long ("HKEY_LOCAL_MACHINE\...") format. Key may be an existing key or a new (non-existing) key. .PARAMETER Display Display console messages (effective only for user-interactive sessions). .EXAMPLE $ozoRegistryKey = (Get-OZORegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion" -Display) Using key path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion. Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion exists and all values read. Name Type Value ---- ---- ---- ProgramFilesDir String C:\Program Files CommonFilesDir String C:\Program Files\Common Files ProgramFilesDir (x86) String C:\Program Files (x86) CommonFilesDir (x86) String C:\Program Files (x86)\Common Files CommonW6432Dir String C:\Program Files\Common Files DevicePath ExpandString %SystemRoot%\inf MediaPathUnexpanded ExpandString %SystemRoot%\Media ProgramFilesPath ExpandString %ProgramFiles% ProgramW6432Dir String C:\Program Files .EXAMPLE $ozoRegistryKey = (Get-OZORegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion") .EXAMPLE $ozoRegistryKey = (Get-OZORegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion") $ozoRegistryKey.DisplayKeyValues() $ozoRegistryKey.SetDisplay($true) $ozoRegistryKey.DisplayKeyValues() Name Type Value ---- ---- ---- ProgramFilesDir String C:\Program Files CommonFilesDir String C:\Program Files\Common Files ProgramFilesDir (x86) String C:\Program Files (x86) CommonFilesDir (x86) String C:\Program Files (x86)\Common Files CommonW6432Dir String C:\Program Files\Common Files DevicePath ExpandString %SystemRoot%\inf MediaPathUnexpanded ExpandString %SystemRoot%\Media ProgramFilesPath ExpandString %ProgramFiles% ProgramW6432Dir String C:\Program Files ``` .EXAMPLE $ozoRegistryKey = (Get-OZORegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion") $ozoRegistryKey.ReturnKeyNameValue("ProgramFilesDir") C:\Program Files $ozoRegistryKey.ReturnKeyNameType("ProgramFilesDIr") String .EXAMPLE $ozoRegistryKey = (Get-OZORegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\One Zero One") If (($ozoRegistryKey.AddKeyName("Version","1.0.0")) -eq $true) { $ozoRegistryKey.ProcessChanges() } .EXAMPLE $ozoRegistryKey = (Get-OZORegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\One Zero One") If (($ozoRegistryKey.UpdateKeyName("Version","2.0.0")) -eq $true) { $ozoRegistryKey.ProcessChanges() } .EXAMPLE $ozoRegistryKey = (Get-OZORegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\One Zero One") If (($ozoRegistryKey.UpdateName("Version")) -eq $true) { $ozoRegistryKey.ProcessChanges() } .LINK https://github.com/onezeroone-dev/OZORegistry-PowerShell-Module/blob/main/Documentation/Get-OZORegistryKey.md .NOTES Messages as written to the Windows Event Viewer One Zero One provider when available. Otherwise, messages are written to the Microsoft-Windows-PowerShell provider under event ID 4100. #> [CmdLetBinding()] Param ( [Parameter(Mandatory=$true,HelpMessage="The registry key")][String]$Key, [Parameter(Mandatory=$false,HelpMessage="Display console messages")][Switch]$Display ) # Return an OZORegistryKey object If ($Display -eq $true ) { $PSCmdlet.WriteObject(([OZORegistryKey]::new($Key,$true))) } Else { $PSCmdlet.WriteObject(([OZORegistryKey]::new($Key,$false))) } } Function Read-OZORegistryKeyNameValue { <# .SYNOPSIS See description. .DESCRIPTION A simple function for returning the value for a single registry key name. Returns "Key path is not valid" if the path is not valid, "Key not found" if the path does not exist, "Could not read key names" if the key names could not be read, and "Unhandled data type" if the data cannot be returned. .PARAMETER Key The registry key. .PARAMETER Name The key name. .EXAMPLE Read-OZORegistryKeyNameValue -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion" -Name "ProgramFilesDir" C:\Program Files .EXAMPLE Read-OZORegistryKeyNameValue -Key "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion" -Name "ProgramFilesDir" C:\Program Files .LINK https://github.com/onezeroone-dev/OZORegistry-PowerShell-Module/blob/main/Documentation/Read-OZORegistryKeyNameValue.md .NOTES Messages as written to the Windows Event Viewer One Zero One provider when available. Otherwise, messages are written to the Microsoft-Windows-PowerShell provider under event ID 4100. #> # Parameters [CmdletBinding()] Param ( [Parameter(Mandatory=$true,HelpMessage="The registry key")][String]$Key, [Parameter(Mandatory=$true,HelpMessage="The key name")][String]$Name ) # Instantiate an OZORegistryKey object and return the value data return ([OZORegistryKey]::new($Key,$false)).ReturnKeyNameValue($Name) } Function Read-OZORegistryKeyNameType { <# .SYNOPSIS See description. .DESCRIPTION A simple function for returning the _type_ of a single registry key name. Returns "Key path is not valid" if the path is not valid, "Key not found" if the path does not exist, "Could not read key names" if the key names could not be read, and "Unhandled data type" if the data cannot be returned. .PARAMETER Key The registry key. .PARAMETER Name The key name. .EXAMPLE Read-OZORegistryKeyNameType -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion" -Name "ProgramFilesDir" String .EXAMPLE Read-OZORegistryKeyNameType -Key "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion" -Name "ProgramFilesDir" String .LINK https://github.com/onezeroone-dev/OZORegistry-PowerShell-Module/blob/main/Documentation/Read-OZORegistryKeyNameType.md .NOTES Messages as written to the Windows Event Viewer One Zero One provider when available. Otherwise, messages are written to the Microsoft-Windows-PowerShell provider under event ID 4100. #> # Parameters [CmdletBinding()] Param ( [Parameter(Mandatory=$true,HelpMessage="The registry key")][String]$Key, [Parameter(Mandatory=$true,HelpMessage="The key name")][String]$Name ) # Instantiate an OZORegistryKey object and return the value type return ([OZORegistryKey]::new($Key,$false)).ReturnKeyNameType($Name) } Function Write-OZORegistryKeyNameValue { <# .SYNOPSIS See description. .DESCRIPTION A simple function for adding or updating a single registry key name. If the key + name does not exist, it will be created. If it does exist, it will be updated. Returns True on success and False on failure. Failures are typically due to inadequate permissions or type mismatches. .PARAMETER Key The registry key. .PARAMETER Name The key name. .PARAMETER Value The name value. .PARAMETER Type The type. Valid types are "Binary", "Dword", "ExpandString", "MultString", "Qword", and "String". Defaults to "String". .EXAMPLE Write-OZORegistryKeyValueData -Key "HKEY_LOCAL_MACHINE\SOFTWARE\One Zero One" -Value "Acronym" -Data "OZO" -Type "String" .LINK https://github.com/onezeroone-dev/OZORegistry-PowerShell-Module/blob/main/Documentation/Write-OZORegistryKeyNameValue.md .NOTES Requires Administrator privileges. Messages as written to the Windows Event Viewer One Zero One provider when available. Otherwise, messages are written to the Microsoft-Windows-PowerShell provider under event ID 4100. #> # Parameters [CmdletBinding()] Param ( [Parameter(Mandatory=$true,HelpMessage="The registry key")][String]$Key, [Parameter(Mandatory=$true,HelpMessage="The key name")][String]$Name, [Parameter(Mandatory=$true,HelpMessage="The name value")]$Value, [Parameter(Mandatory=$false,HelpMessage="The type")][ValidateSet("Binary","Dword","ExpandString","MultString","Qword","String")][String]$Type = "String" ) # Instantiate an OZORegistryKey object and return the result of UpdateKeyValue [PSCustomObject] $ozoRegistryKey = ([OZORegistryKey]::new($Key,$false)) # Determine if the name + value can be updated or added If ($ozoRegistryKey.UpdateKeyName($Name,$Value) -eq $true) { # Name + value added; return the result of ProcessChanges return ($ozoRegistryKey.ProcessChanges()) } } Export-ModuleMember -Function Convert-OZORegistryString,Get-OZORegistryKey,Read-OZORegistryKeyNameValue,Read-OZORegistryKeyNameType,Write-OZORegistryKeyNameValue # SIG # Begin signature block # MIIfcQYJKoZIhvcNAQcCoIIfYjCCH14CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCC5rQN+lvF0wRS/ # 7RcGtRElngh/dIc1LLivpN+wm1RjzqCCDPgwggZyMIIEWqADAgECAghkM1HTxzif # CDANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx # EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8G # A1UEAwwoU1NMLmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTAe # Fw0xNjA2MjQyMDQ0MzBaFw0zMTA2MjQyMDQ0MzBaMHgxCzAJBgNVBAYTAlVTMQ4w # DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENv # cnAxNDAyBgNVBAMMK1NTTC5jb20gQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBD # QSBSU0EgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCfgxNzqrDG # bSHL24t6h3TQcdyOl3Ka5LuINLTdgAPGL0WkdJq/Hg9Q6p5tePOf+lEmqT2d0bKU # Vz77OYkbkStW72fL5gvjDjmMxjX0jD3dJekBrBdCfVgWQNz51ShEHZVkMGE6ZPKX # 13NMfXsjAm3zdetVPW+qLcSvvnSsXf5qtvzqXHnpD0OctVIFD+8+sbGP0EmtpuNC # GVQ/8y8Ooct8/hP5IznaJRy4PgBKOm8yMDdkHseudQfYVdIYyQ6KvKNc8HwKp4WB # wg6vj5lc02AlvINaaRwlE81y9eucgJvcLGfE3ckJmNVz68Qho+Uyjj4vUpjGYDdk # jLJvSlRyGMwnh/rNdaJjIUy1PWT9K6abVa8mTGC0uVz+q0O9rdATZlAfC9KJpv/X # gAbxwxECMzNhF/dWH44vO2jnFfF3VkopngPawismYTJboFblSSmNNqf1x1KiVgMg # Lzh4gL32Bq5BNMuURb2bx4kYHwu6/6muakCZE93vUN8BuvIE1tAx3zQ4XldbyDge # VtSsSKbt//m4wTvtwiS+RGCnd83VPZhZtEPqqmB9zcLlL/Hr9dQg1Zc0bl0EawUR # 0tOSjAknRO1PNTFGfnQZBWLsiePqI3CY5NEv1IoTGEaTZeVYc9NMPSd6Ij/D+KNV # t/nmh4LsRR7Fbjp8sU65q2j3m2PVkUG8qQIDAQABo4H7MIH4MA8GA1UdEwEB/wQF # MAMBAf8wHwYDVR0jBBgwFoAU3QQJB6L1en1SUxKSle44gCUNplkwMAYIKwYBBQUH # AQEEJDAiMCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcHMuc3NsLmNvbTARBgNVHSAE # CjAIMAYGBFUdIAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwOwYDVR0fBDQwMjAwoC6g # LIYqaHR0cDovL2NybHMuc3NsLmNvbS9zc2wuY29tLXJzYS1Sb290Q0EuY3JsMB0G # A1UdDgQWBBRUwv4QlQCTzWr158DX2bJLuI8M4zAOBgNVHQ8BAf8EBAMCAYYwDQYJ # KoZIhvcNAQELBQADggIBAPUPJodwr5miyvXWyfCNZj05gtOII9iCv49UhCe204MH # 154niU2EjlTRIO5gQ9tXQjzHsJX2vszqoz2OTwbGK1mGf+tzG8rlQCbgPW/M9r1x # xs19DiBAOdYF0q+UCL9/wlG3K7V7gyHwY9rlnOFpLnUdTsthHvWlM98CnRXZ7WmT # V7pGRS6AvGW+5xI+3kf/kJwQrfZWsqTU+tb8LryXIbN2g9KR+gZQ0bGAKID+260P # Z+34fdzZcFt6umi1s0pmF4/n8OdX3Wn+vF7h1YyfE7uVmhX7eSuF1W0+Z0duGwdc # +1RFDxYRLhHDsLy1bhwzV5Qe/kI0Ro4xUE7bM1eV+jjk5hLbq1guRbfZIsr0WkdJ # LCjoT4xCPGRo6eZDrBmRqccTgl/8cQo3t51Qezxd96JSgjXktefTCm9r/o35pNfV # HUvnfWII+NnXrJlJ27WEQRQu9i5gl1NLmv7xiHp0up516eDap8nMLDt7TAp4z5T3 # NmC2gzyKVMtODWgqlBF1JhTqIDfM63kXdlV4cW3iSTgzN9vkbFnHI2LmvM4uVEv9 # XgMqyN0eS3FE0HU+MWJliymm7STheh2ENH+kF3y0rH0/NVjLw78a3Z9UVm1F5VPz # iIorMaPKPlDRADTsJwjDZ8Zc6Gi/zy4WZbg8Zv87spWrmo2dzJTw7XhQf+xkR6Od # MIIGfjCCBGagAwIBAgIQZ2iSsNbwOsjnLExSAX6F6DANBgkqhkiG9w0BAQsFADB4 # MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24x # ETAPBgNVBAoMCFNTTCBDb3JwMTQwMgYDVQQDDCtTU0wuY29tIENvZGUgU2lnbmlu # ZyBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIxMB4XDTI0MTExNjEwMzUyOFoXDTI1MTEx # NjEwMzUyOFowZTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYD # VQQHDAZEZW52ZXIxGDAWBgNVBAoMD0FuZHJldyBMaWV2ZXJ0ejEYMBYGA1UEAwwP # QW5kcmV3IExpZXZlcnR6MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA # vIBAQzK0aahepOrPmvCEqfd6dMZC4GvV7kflKwrn4QPJGfqhFmUtadP1e3ange8O # QZ3/w7UjOTAUNUHfhjbSgUBlKjbS6EWQKZuRFzI3SNkMJkcjTX4uS2P4QsnwM+SW # IE5me3CTssdjtgue+Iiy53TMgW8JpoxiULVxmm3bhCRUAgxWeT6tzjytR1UyGcMc # cm/YE6TOgsCHiZoo4X4HJD9iHDrNldArq04Jl6FsADxEswttKyfqpIRJLoAysVl1 # f8CEDBwhszJrEXBnAlWViJFfNY+dKP4jhf7lLqSvPCuADqP2jvM0Ym5I8qDGMz9j # XPSMLF58MFB4vM4viS7nLRFJ8S1Q98vQvB8W4kk0WPuiZbZTHsROzohE1VSbLnIY # ag5dDOWI8L6yutAsfdZFYFmSTKcMSiOj5VbK4LhAJUL2G8vPwpTGFgr+cEp0p62F # P0WXK+/cRfGqodI5S+bg+9rQTD9zf829DwraSRAt5P5zrQk4WPst3JW/vIKNx7cV # AgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFFTC/hCVAJPN # avXnwNfZsku4jwzjMHoGCCsGAQUFBwEBBG4wbDBIBggrBgEFBQcwAoY8aHR0cDov # L2NlcnQuc3NsLmNvbS9TU0xjb20tU3ViQ0EtQ29kZVNpZ25pbmctUlNBLTQwOTYt # UjEuY2VyMCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcHMuc3NsLmNvbTBRBgNVHSAE # SjBIMAgGBmeBDAEEATA8BgwrBgEEAYKpMAEDAwEwLDAqBggrBgEFBQcCARYeaHR0 # cHM6Ly93d3cuc3NsLmNvbS9yZXBvc2l0b3J5MBMGA1UdJQQMMAoGCCsGAQUFBwMD # ME0GA1UdHwRGMEQwQqBAoD6GPGh0dHA6Ly9jcmxzLnNzbC5jb20vU1NMY29tLVN1 # YkNBLUNvZGVTaWduaW5nLVJTQS00MDk2LVIxLmNybDAdBgNVHQ4EFgQUSj8HrSK7 # f/j+Dz31jJFhOF7rJUMwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IC # AQBf4lcc6FUJ1W/opNz8yjS9qLUy9cQt0s35BhasB5QoTbDaW4jv9xnFGhQVg6n+ # jhL0i94Vsywd/MRBb8lYGpuBZnS/7LHuRZu7qUuud+IMDyRHIyBK6koN5bfyA5VY # c7bFbNpbe1s1hMWke8di4qgMLZKDfyG/RtA0swf5t4UgQLPP0h+koZ8X8V5+P0V0 # 1HsdXyXd+ojo38EoZyCKfQL2aAwMPwzZfCbmI5SRXNOc6K8oqXzQcendhlKSfVBo # Zgpi+1updqbD4jmJfYdK5AYPxJ3YH6td6ETtr8owL+bmX8lQjlXPOwVnC11rVlNB # VjqtaJRUClLtiNiYSTKVfjdmGVJ4+sNov0dWhHc0A9o5NX/05VVYTlImuJpnG5Og # o7w6kWRdsgE8gM58jWf7XfI6aQS0Np/z2B+ZBj0K93khEHBX7cvvORa92LCHiVeP # km+zEAMXgxIPs/e8cmcc/o3CORgzEwxlH9Z3UOWCuXSHD3P2RPNDAY+WPdjSHm9f # JFlGq+f9iKyedxYa/NNjNag/5EbZ+Z2NldtSMNeFdsejGJ/TJHF1PyJd4aXx9J1i # B/IZBOoJYyh9xpQ3ljZUKE/4otPi7INpuDFwgWiUHZZJVvrGTWwxH1Yhf8P+VpFf # aNqsBuvklUcUDs3RNE0f1qlgFfcnAepFF+RiBRqmsj29fjGCEc8wghHLAgEBMIGM # MHgxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3Rv # bjERMA8GA1UECgwIU1NMIENvcnAxNDAyBgNVBAMMK1NTTC5jb20gQ29kZSBTaWdu # aW5nIEludGVybWVkaWF0ZSBDQSBSU0EgUjECEGdokrDW8DrI5yxMUgF+hegwDQYJ # YIZIAWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYK # KwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG # 9w0BCQQxIgQg6OzF0q5CjbLxPxOCeof3YDjcL/Cv3xHXF9cO6hXQqz8wDQYJKoZI # hvcNAQEBBQAEggGApHNsb0gLjlYq8C+2fK9t8e9D/J6OGbiMo7n9dVqe8/g39/pk # Eo4aziUaR9fvae3YNA5VSy5h5UcSkKQRpnsuSetFfSPDc88slRsxQa3dWikja5MT # y6tx+BO0Z1TKhgvTWebKSDiopAXFGSL/FDiIpp7x/RXygu4sc8FDbYM/9FidT64L # g7xo2MoLV3SO6ah7QGueYwAZLrjjMAya86jK+f/U11Q83i8k55wHWJLONZbBxmuJ # z5qbiBkMbOtgkA+Q6YBEnHAF+DpnFvtvRi5RxduAL7icn6yC2MXO/fKkgfaqJ82S # a0vKZUQkIk7aHCh2hVG7MJqCEVbh/a98haswK0GodBpbmdJwY69T8WAA5tX0EJvi # 5zzbt5ZK0SJvaroHvsiYYI904iqhNl1Ubt40twJe7b5iVGuKXrRO8ybtW/qWjqcS # SPqvil+JeUI8f/mZIzNgakSUwgaAX5+f3IMiiUtYygWQbmmXzZi4Hvu30KAlVYBR # QF5I5ggHLQQMGZ9EoYIPFTCCDxEGCisGAQQBgjcDAwExgg8BMIIO/QYJKoZIhvcN # AQcCoIIO7jCCDuoCAQMxDTALBglghkgBZQMEAgEwdwYLKoZIhvcNAQkQAQSgaARm # MGQCAQEGDCsGAQQBgqkwAQMGATAxMA0GCWCGSAFlAwQCAQUABCAg1GZef8iJqEmb # BIIA1kBN1SU2E9zJYwA1flkNC3lYJQIIaUIYMCvfAWQYDzIwMjUwNjA1MTg0NjA2 # WjADAgEBoIIMADCCBPwwggLkoAMCAQICEFparOgaNW60YoaNV33gPccwDQYJKoZI # hvcNAQELBQAwczELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQH # DAdIb3VzdG9uMREwDwYDVQQKDAhTU0wgQ29ycDEvMC0GA1UEAwwmU1NMLmNvbSBU # aW1lc3RhbXBpbmcgSXNzdWluZyBSU0EgQ0EgUjEwHhcNMjQwMjE5MTYxODE5WhcN # MzQwMjE2MTYxODE4WjBuMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO # BgNVBAcMB0hvdXN0b24xETAPBgNVBAoMCFNTTCBDb3JwMSowKAYDVQQDDCFTU0wu # Y29tIFRpbWVzdGFtcGluZyBVbml0IDIwMjQgRTEwWTATBgcqhkjOPQIBBggqhkjO # PQMBBwNCAASnYXL1MOl6xIMUlgVC49zonduUbdkyb0piy2i8t3JlQEwA74cjK8g9 # mRC8GH1cAAVMIr8M2HdZpVgkV1LXBLB8o4IBWjCCAVYwHwYDVR0jBBgwFoAUDJ0Q # JY6apxuZh0PPCH7hvYGQ9M8wUQYIKwYBBQUHAQEERTBDMEEGCCsGAQUFBzAChjVo # dHRwOi8vY2VydC5zc2wuY29tL1NTTC5jb20tdGltZVN0YW1waW5nLUktUlNBLVIx # LmNlcjBRBgNVHSAESjBIMDwGDCsGAQQBgqkwAQMGATAsMCoGCCsGAQUFBwIBFh5o # dHRwczovL3d3dy5zc2wuY29tL3JlcG9zaXRvcnkwCAYGZ4EMAQQCMBYGA1UdJQEB # /wQMMAoGCCsGAQUFBwMIMEYGA1UdHwQ/MD0wO6A5oDeGNWh0dHA6Ly9jcmxzLnNz # bC5jb20vU1NMLmNvbS10aW1lU3RhbXBpbmctSS1SU0EtUjEuY3JsMB0GA1UdDgQW # BBRQTySs77U+YxMjCZIm7Lo6luRdIjAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcN # AQELBQADggIBAJigjwMAkbyrxGRBf0Ih4r+rbCB57lTuwViC6nH2fZSciMogpqSz # rSeVZ2eIb5vhj9rT7jqWXZn02Fncs4YTrA1QyxJW36yjC4jl5/bsFCaWuXzGXt2Y # 6Ifp//A3Z0sNTMWTTBobmceM3sqnovdX9ToRFP+29r5yQnPcgRTI2PvrVSqLxY9E # yk9/0cviM3W29YBl080ENblRcu3Y8RsfzRtVT/2snuDocRxvRYmd0TPaMgIj2xII # 651QnPp1hiq9xU0AyovLzbsi5wlR5Ip4i/i8+x+HwYJNety5cYtdWJ7uQP6YaZtW # /jNoHp76qNftq/IlSx6xEYBRjFBxHSq2fzhUQ5oBawk2OsZ2j0wOf7q7AqjCt6t/ # +fbmWjrAWYWZGj/RLjltqdFPBpIKqdhjVIxaGgzVhaE/xHKBg4k4DfFZkBYJ9BWu # P93Tm+paWBDwXI7Fg3alGsboErWPWlvwMAmpeJUjeKLZY26JPLt9ZWceTVWuIyuj # erqb5IMmeqLJm5iFq/Qy4YPGyPiolw5w1k9OeO4ErmS2FKvk1ejvw4SWR+S1VyWn # ktY442WaoStxBCCVWZdMWFeB+EpL8uoQNq1MhSt/sIUjUudkyZLIbMVQjj7b6gPX # nD6mS8FgWiCAhuM1a/hgA+6o1sJWizHdmcpYDhyNzorf9KVRE6iR7rcmMIIG/DCC # BOSgAwIBAgIQbVIYcIfoI02FYADQgI+TVjANBgkqhkiG9w0BAQsFADB8MQswCQYD # VQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xGDAWBgNV # BAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBSb290IENlcnRp # ZmljYXRpb24gQXV0aG9yaXR5IFJTQTAeFw0xOTExMTMxODUwMDVaFw0zNDExMTIx # ODUwMDVaMHMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwH # SG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxLzAtBgNVBAMMJlNTTC5jb20gVGlt # ZXN0YW1waW5nIElzc3VpbmcgUlNBIENBIFIxMIICIjANBgkqhkiG9w0BAQEFAAOC # Ag8AMIICCgKCAgEArlEQE9L5PCCgIIXeyVAcZMnh/cXpNP8KfzFI6HJaxV6oYf3x # h/dRXPu35tDBwhOwPsJjoqgY/Tg6yQGBqt65t94wpx0rAgTVgEGMqGri6vCI6rEt # SZVy9vagzTDHcGfFDc0Eu71mTAyeNCUhjaYTBkyANqp9m6IRrYEXOKdd/eREsqVD # mhryd7dBTS9wbipm+mHLTHEFBdrKqKDM3fPYdBOro3bwQ6OmcDZ1qMY+2Jn1o0l4 # N9wORrmPcpuEGTOThFYKPHm8/wfoMocgizTYYeDG/+MbwkwjFZjWKwb4hoHT2WK8 # pvGW/OE0Apkrl9CZSy2ulitWjuqpcCEm2/W1RofOunpCm5Qv10T9tIALtQo73GHI # lIDU6xhYPH/ACYEDzgnNfwgnWiUmMISaUnYXijp0IBEoDZmGT4RTguiCmjAFF5OV # NbY03BQoBb7wK17SuGswFlDjtWN33ZXSAS+i45My1AmCTZBV6obAVXDzLgdJ1A1r # yyXz4prLYyfJReEuhAsVp5VouzhJVcE57dRrUanmPcnb7xi57VPhXnCuw26hw1Hd # +ulK3jJEgbc3rwHPWqqGT541TI7xaldaWDo85k4lR2bQHPNGwHxXuSy3yczyOg57 # TcqqG6cE3r0KR6jwzfaqjTvN695GsPAPY/h2YksNgF+XBnUD9JBtL4c34AcCAwEA # AaOCAYEwggF9MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAU3QQJB6L1 # en1SUxKSle44gCUNplkwgYMGCCsGAQUFBwEBBHcwdTBRBggrBgEFBQcwAoZFaHR0 # cDovL3d3dy5zc2wuY29tL3JlcG9zaXRvcnkvU1NMY29tUm9vdENlcnRpZmljYXRp # b25BdXRob3JpdHlSU0EuY3J0MCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcHMuc3Ns # LmNvbTA/BgNVHSAEODA2MDQGBFUdIAAwLDAqBggrBgEFBQcCARYeaHR0cHM6Ly93 # d3cuc3NsLmNvbS9yZXBvc2l0b3J5MBMGA1UdJQQMMAoGCCsGAQUFBwMIMDsGA1Ud # HwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmxzLnNzbC5jb20vc3NsLmNvbS1yc2EtUm9v # dENBLmNybDAdBgNVHQ4EFgQUDJ0QJY6apxuZh0PPCH7hvYGQ9M8wDgYDVR0PAQH/ # BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQCSGXUNplpCzxkH2fL8lPrAm/AV6USW # Wi9xM91Q5RN7mZN3D8T7cm1Xy7qmnItFukgdtiUzLbQokDJyFTrF1pyLgGw/2hU3 # FJEywSN8crPsBGo812lyWFgAg0uOwUYw7WJQ1teICycX/Fug0KB94xwxhsvJBiRT # pQyhu/2Kyu1Bnx7QQBA1XupcmfhbQrK5O3Q/yIi//kN0OkhQEiS0NlyPPYoRboHW # C++wogzV6yNjBbKUBrMFxABqR7mkA0x1Kfy3Ud08qyLC5Z86C7JFBrMBfyhfPpKV # lIiiTQuKz1rTa8ZW12ERoHRHcfEjI1EwwpZXXK5J5RcW6h7FZq/cZE9kLRZhvnRK # tb+X7CCtLx2h61ozDJmifYvuKhiUg9LLWH0Or9D3XU+xKRsRnfOuwHWuhWch8G7k # EmnTG9CtD9Dgtq+68KgVHtAWjKk2ui1s1iLYAYxnDm13jMZm0KpRM9mLQHBK5Gb4 # dFgAQwxOFPBslf99hXWgLyYE33vTIi9p0gYqGHv4OZh1ElgGsvyKdUUJkAr5hfbD # X6pYScJI8v9VNYm1JEyFAV9x4MpskL6kE2Sy8rOqS9rQnVnIyPWLi8N9K4GZvPit # /Oy+8nFL6q5kN2SZbox5d69YYFe+rN1sDD4CpNWwBBTI/q0V4pkgvhL99IV2Xasj # HZf4peSrHdL4RjGCAlcwggJTAgEBMIGHMHMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI # DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxLzAt # BgNVBAMMJlNTTC5jb20gVGltZXN0YW1waW5nIElzc3VpbmcgUlNBIENBIFIxAhBa # WqzoGjVutGKGjVd94D3HMAsGCWCGSAFlAwQCAaCCAWEwGgYJKoZIhvcNAQkDMQ0G # CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNTA2MDUxODQ2MDZaMCgGCSqG # SIb3DQEJNDEbMBkwCwYJYIZIAWUDBAIBoQoGCCqGSM49BAMCMC8GCSqGSIb3DQEJ # BDEiBCCz/FWaEHO8V7/opBn8X5gX9eh98zmlInUgEeVqKTA7RjCByQYLKoZIhvcN # AQkQAi8xgbkwgbYwgbMwgbAEIJ1xf43CN2Wqzl5KsOH1ddeaF9Qc7tj9r+8D/T29 # iUfnMIGLMHekdTBzMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNV # BAcMB0hvdXN0b24xETAPBgNVBAoMCFNTTCBDb3JwMS8wLQYDVQQDDCZTU0wuY29t # IFRpbWVzdGFtcGluZyBJc3N1aW5nIFJTQSBDQSBSMQIQWlqs6Bo1brRiho1XfeA9 # xzAKBggqhkjOPQQDAgRGMEQCIEhB1p1U6qBG6OCzh3FXYjP6I+k/5rC34wccJIsI # ag0VAiAf+eZCsQwcIJJL3LvjZoWf4JZXPrrzho7A7ErkmiWNFg== # SIG # End signature block |