PSWMIRegistry.psm1
# PSWMIRegistry module compiled on 2023-03-18 22:53:12 # <# .SYNOPSIS Parses a registry path, normalizing the hive dsignation. .DESCRIPTION Parses a registry path, normalizing the hive designation. So, HKLM\FirstKey\SecondKey HKLM:\FirstKey\SecondKey HKEY_LOCAL_MACHINE\FirstKey\SecondKey will all normalize to HKLM as a hive and FirstKey\SecondKey as the path below the hive. .PARAMETER Path [string] Path to be parsed. .EXAMPLE PS> Parse-RegistryPath -Path "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Something" Hive HiveKey Path ---- ------- ---- HKCU 2147483649 SOFTWARE\Microsoft\Something .INPUTS [string] path to be parsed .OUTPUTS [PSCustomObject] conaining the normalized hive designation, the path below the hive and the integer HiveID for RegStdProv. $null, if the path could not be parsed. #> function Parse-RegistryPath { [CmdletBinding()] Param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string]$Path ) $hiveMap = @{ 'HKCR' = 'HKCR' 'HKCR:' = 'HKCR' 'HKEY_CLASSES_ROOT' = 'HKCR' 'HKCU' = 'HKCU' 'HKCU:' = 'HKCU' 'HKEY_CURRENT_USER' = 'HKCU' 'HKLM' = 'HKLM' 'HKLM:' = 'HKLM' 'HKEY_LOCAL_MACHINE' = 'HKLM' 'HKU' = 'HKU' 'HKU:' = 'HKU' 'HKEY_USERS' = 'HKU' 'HKCC' = 'HKCC' 'HKCC:' = 'HKCC' 'HKEY_CURRENT_CONFIG' = 'HKCC' } $hiveValue = @{ 'HKCR' = 2147483648 'HKCU' = 2147483649 'HKLM' = 2147483650 'HKU' = 2147483651 'HKCC' = 2147483653 } $Path = $Path.Trim("\") $Hive = $Path.Split("\",2)[0] if ($hiveMap.ContainsKey($Hive)) { $res = [PSCustomObject]@{ 'Hive' = $hiveMap[$Hive] 'HiveKey' = $hiveValue[$hiveMap[$Hive]] 'Path' = $Path.Split("\",2)[1] } } else { Write-Warning ('Hive designation {0} is not valid. Valid values are {1}' -f $Hive, ($hiveMap.keys -join ', ')) $res = $null } return $res } <# .SYNOPSIS Returns the value of a registry value in a specified path. .DESCRIPTION Returns the value of a registry value in a specified path. .PARAMETER Hostname [string] Name or IP address of the remote computer. Defaults to '.'. .PARAMETER Credential [PSCredential] Credential used to access the remote computer. .PARAMETER Path [string] Path to the key containing the value. .PARAMETER Name [string] Name of the registry value to read. .EXAMPLE PS> Get-WMIRegistryValue -Path "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Something" -Name "Version" 1.1.0.5 .INPUTS None .OUTPUTS $null, if the path could not be parsed or the registry value does not exist. Various types, depending on the type of the registry value. #> function Get-WMIRegistryValue { [CmdletBinding()] Param( [Parameter(Mandatory=$false)] [string]$Hostname = '.', [Parameter(Mandatory=$false)] [PSCredential]$Credential, [Parameter(Mandatory=$true)] [string]$Path, [Parameter(Mandatory=$true)] [string]$Name ) $parsedPath = Parse-RegistryPath -Path $Path if ($null -eq $parsedPath) { return $null } $type = $null $msPath = ('\\{0}\ROOT\DEFAULT:StdRegProv' -f $Hostname) $mScope = New-Object System.Management.ManagementScope($msPath) if ($null -ne $Credential) { $mScope.Options.Username = $Credential.UserName $mScope.Options.SecurePassword = $Credential.Password } try { $mScope.Connect() } catch { Write-Warning ('Error connecting management scope: {0}' -f $_.Exception.Message) return $null } $regObject = New-Object System.Management.ManagementClass($mScope, $msPath, $null) try { $res = $regObject.EnumValues($parsedPath.HiveKey, $parsedPath.Path) } catch { Write-Warning ('Error accessing key: {0}' -f $_.Exception.Message) return $null } if ($res.ReturnValue -ne 0) { Write-Warning ('Key not found: {0}' -f $Path) return $null } else { $valIndex = -1 for ($i = 0; $i -lt $res.sNames.Count; $i++) { if ($res.sNames[$i] -ieq $Name) { $valIndex = $i $type = $res.Types[$i] $valName = $res.sNames[$i] break } } } if ($valIndex -gt -1) { switch ($type) { 1 { #REG_SZ $res = $regObject.GetStringValue($parsedPath.HiveKey, $parsedPath.Path, $valName) return $res.sValue } 2 { #REG_EXPAND_SZ $res = $regObject.GetExpandedStringValue($parsedPath.HiveKey, $parsedPath.Path, $valName) return $res.sValue } 3 { #REG_BINARY $res = $regObject.GetBinaryValue($parsedPath.HiveKey, $parsedPath.Path, $valName) return $res.uValue } 4 { #REG_DWORD $res = $regObject.GetDWORDValue($parsedPath.HiveKey, $parsedPath.Path, $valName) return $res.uValue } 7 { #REG_MULTI_SZ $res = $regObject.GetMultiStringValue($parsedPath.HiveKey, $parsedPath.Path, $valName) return $res.sValue } 11 { #REG_QWORD $res = $regObject.GetQWORDValue($parsedPath.HiveKey, $parsedPath.Path, $valName) return $res.uValue } default { Write-Warning ('Type [{0}] is not implemented.' -f $type) return $null } } } else { Write-Warning ('Value not found: {0}' -f $Name) return $null } } <# .SYNOPSIS Creates a registry key. .DESCRIPTION Creates a registry key. .PARAMETER Hostname [string] Name or IP address of the remote computer. Defaults to '.'. .PARAMETER Credential [PSCredential] Credential used to access the remote computer. .PARAMETER Path [string] Path to the key containing the value. .PARAMETER Name [string] Name of the registry value to read. .EXAMPLE PS> New-WMIRegistryKey -Path "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Something" -Name "Version" True .INPUTS None .OUTPUTS $null, if the path could not be parsed or the registry value does not exist. $true or $false, depending on whether the key could be created. #> function New-WMIRegistryKey { [CmdletBinding()] Param( [Parameter(Mandatory=$false)] [string]$Hostname = '.', [Parameter(Mandatory=$false)] [PSCredential]$Credential, [Parameter(Mandatory=$true)] [string]$Path, [Parameter(Mandatory=$true)] [string]$Name ) $parsedPath = Parse-RegistryPath -Path $Path if ($null -eq $parsedPath) { return $null } $msPath = ('\\{0}\ROOT\DEFAULT:StdRegProv' -f $Hostname) $mScope = New-Object System.Management.ManagementScope($msPath) if ($null -ne $Credential) { $mScope.Options.Username = $Credential.UserName $mScope.Options.SecurePassword = $Credential.Password } try { $mScope.Connect() } catch { Write-Warning ('Error connecting management scope: {0}' -f $_.Exception.Message) return $null } $regObject = New-Object System.Management.ManagementClass($mScope, $msPath, $null) try { $res = $regObject.EnumKey($parsedPath.HiveKey, $parsedPath.Path) } catch { Write-Warning ('Error accessing key: {0}' -f $_.Exception.Message) return $null } if ($res.ReturnValue -ne 0) { return $false } else { $valIndex = -1 for ($i = 0; $i -lt $res.sNames.Count; $i++) { if ($res.sNames[$i] -ieq $Name) { $valIndex = $i break } } if ($valIndex -gt -1) { Write-Warning 'Registry key already exists in this path!' return $false } else { $newPath = ('{0}\{1}' -f $parsedPath.Path, $Name) $res = $regObject.CreateKey($parsedPath.HiveKey, $newPath) return ($res.ReturnValue -eq 0) } } } <# .SYNOPSIS Removes a registry value from a specified path. .DESCRIPTION Removes a registry value from a specified path. .PARAMETER Hostname [string] Name or IP address of the remote computer. Defaults to '.'. .PARAMETER Credential [PSCredential] Credential used to access the remote computer. .PARAMETER Path [string] Path to the key containing the value. .PARAMETER Name [string] Name of the registry value to remove. .EXAMPLE PS> Remove-WMIRegistryValue -Path "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Something" -Name "Version" True .INPUTS None .OUTPUTS $null, if the path could not be parsed or the registry value does not exist. $true, if the value could be removed. $false, if the value could not be removed. #> function Remove-WMIRegistryValue { [CmdletBinding(SupportsShouldProcess)] Param( [Parameter(Mandatory=$false)] [string]$Hostname = '.', [Parameter(Mandatory=$false)] [PSCredential]$Credential, [Parameter(Mandatory=$true)] [string]$Path, [Parameter(Mandatory=$true)] [string]$Name ) $parsedPath = Parse-RegistryPath -Path $Path if ($null -eq $parsedPath) { return $null } $type = $null $msPath = ('\\{0}\ROOT\DEFAULT:StdRegProv' -f $Hostname) $mScope = New-Object System.Management.ManagementScope($msPath) if ($null -ne $Credential) { $mScope.Options.Username = $Credential.UserName $mScope.Options.SecurePassword = $Credential.Password } try { $mScope.Connect() } catch { Write-Warning ('Error connecting management scope: {0}' -f $_.Exception.Message) return $null } $regObject = New-Object System.Management.ManagementClass($mScope, $msPath, $null) try { $res = $regObject.EnumValues($parsedPath.HiveKey, $parsedPath.Path) } catch { Write-Warning ('Error accessing key: {0}' -f $_.Exception.Message) return $null } if ($res.ReturnValue -ne 0) { Write-Warning ('Key not found: {0}' -f $Path) return $null } else { $valIndex = -1 for ($i = 0; $i -lt $res.sNames.Count; $i++) { if ($res.sNames[$i] -ieq $Name) { $valIndex = $i $type = $res.Types[$i] $valName = $res.sNames[$i] break } } } if ($valIndex -gt -1) { $shpPath = ('\\{0}\{1}\{2}\{3}' -f $Hostname, $parsedPath.Hive, $parsedPath.Path, $valName) if($PSCmdlet.ShouldProcess($shpPath, 'DeleteValue')){ $res = $regObject.DeleteValue($parsedPath.HiveKey, $parsedPath.Path, $valName) return ($res.ReturnValue -eq 0) } else { return $true } } else { Write-Warning ('Value not found: {0}' -f $Name) return $null } } <# .SYNOPSIS Sets the value of a registry value in a specified path. .DESCRIPTION Sets the value of a registry value in a specified path. If the value does not exist, it is created. .PARAMETER Hostname [string] Name or IP address of the remote computer. Defaults to '.'. .PARAMETER Credential [PSCredential] Credential used to access the remote computer. .PARAMETER Path [string] Path to the key containing the value. .PARAMETER Name [string] Name of the registry value to set or add. .PARAMETER Type [string] Type of the registry value to set or add. .PARAMETER Value [string] Value of the registry value to set or add. .EXAMPLE PS> Set-WMIRegistryValue -Path "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Something" -Name "Version" -Type REG_SZ -Value "1.0.0.1" True .INPUTS None .OUTPUTS $null, if the path could not be parsed or the registry value does not exist. $true, if the value could be added. $false, if the value could not be added. #> function Set-WMIRegistryValue { [CmdletBinding()] Param( [Parameter(Mandatory=$false)] [string]$Hostname = '.', [Parameter(Mandatory=$false)] [PSCredential]$Credential, [Parameter(Mandatory=$true)] [string]$Path, [Parameter(Mandatory=$true)] [string]$Name, [Parameter(Mandatory=$false)] [ValidateSet('REG_SZ','REG_EXPAND_SZ','REG_BINARY','REG_DWORD','REG_MULTI_SZ','REG_QWORD')] [string]$Type = 'REG_SZ', [Parameter(Mandatory=$true)] [object]$Value ) switch ($Type) { 'REG_SZ' { $zValue = $Value.ToString() } 'REG_EXPAND_SZ' { $zValue = $Value.ToString() } 'REG_MULTI_SZ' { $zValue = $Value.Foreach({$_.ToString()}) } 'REG_DWORD' { $zValue = $Value -as [int] } 'REG_QWORD' { $zValue = $Value -as [int64] } 'REG_BINARY' { if ($value.GetType().Name -eq 'Byte[]') { $zValue = $Value } else { $zValue = $null } } } if ($null -eq $zValue) { Write-Warning ('Cannot convert the supplied value into {0}' -f $Type) return $false } $parsedPath = Parse-RegistryPath -Path $Path if ($null -eq $parsedPath) { return $null } $valType = $null $msPath = ('\\{0}\ROOT\DEFAULT:StdRegProv' -f $Hostname) $mScope = New-Object System.Management.ManagementScope($msPath) if ($null -ne $Credential) { $mScope.Options.Username = $Credential.UserName $mScope.Options.SecurePassword = $Credential.Password } try { $mScope.Connect() } catch { Write-Warning ('Error connecting management scope: {0}' -f $_.Exception.Message) return $null } $regObject = New-Object System.Management.ManagementClass($mScope, $msPath, $null) try { $res = $regObject.EnumValues($parsedPath.HiveKey, $parsedPath.Path) } catch { Write-Warning ('Error accessing key: {0}' -f $_.Exception.Message) return $null } if ($res.ReturnValue -ne 0) { Write-Warning ('Key not found: {0}' -f $Path) return $null } else { $valIndex = -1 for ($i = 0; $i -lt $res.sNames.Count; $i++) { if ($res.sNames[$i] -ieq $Name) { $valIndex = $i $valType = $res.Types[$i] $valName = $res.sNames[$i] break } } } $canAdd = $true if ($valIndex -gt -1) { switch ($valType) { 1 { #REG_SZ $exType = 'REG_SZ' if ($Type -ne 'REG_SZ') { $canAdd = $false } } 2 { #REG_EXPAND_SZ $exType = 'REG_EXPAND_SZ' if ($Type -ne 'REG_EXPAND_SZ') { $canAdd = $false } } 3 { #REG_BINARY $exType = 'REG_BINARY' if ($Type -ne 'REG_BINARY') { $canAdd = $false } } 4 { #REG_DWORD $exType = 'REG_DWORD' if ($Type -ne 'REG_DWORD') { $canAdd = $false } } 7 { #REG_MULTI_SZ $exType = 'REG_MULTI_SZ' if ($Type -ne 'REG_MULTI_SZ') { $canAdd = $false } } 11 { #REG_QWORD $exType = 'REG_QWORD' if ($Type -ne 'REG_QWORD') { $canAdd = $false } } default { Write-Warning ('Type [{0}] is not implemented.' -f $type) $exType = 'undefined' $canAdd = $false } } } else { $valName = $Name } if ($canAdd) { switch ($Type) { 'REG_SZ' { $res = $regObject.SetStringValue($parsedPath.HiveKey, $parsedPath.Path, $valName, $zValue) } 'REG_EXPAND_SZ' { $res = $regObject.SetExpandedStringValue($parsedPath.HiveKey, $parsedPath.Path, $valName, $zValue) } 'REG_MULTI_SZ' { $res = $regObject.SetMultiStringValue($parsedPath.HiveKey, $parsedPath.Path, $valName, $zValue) } 'REG_DWORD' { $res = $regObject.SetDWORDValue($parsedPath.HiveKey, $parsedPath.Path, $valName, $zValue) } 'REG_QWORD' { $res = $regObject.SetQWORDValue($parsedPath.HiveKey, $parsedPath.Path, $valName, $zValue) } 'REG_BINARY' { $res = $regObject.SetBinaryValue($parsedPath.HiveKey, $parsedPath.Path, $valName, $zValue) } } return ($res.ReturnValue -eq 0) } else { Write-Warning ('Value is already present and its type ({0}) does not match the specified type ({1})' -f $exType, $Type) } } <# .SYNOPSIS Tests for the existence of a registry path. .DESCRIPTION Tests for the existence of a registry path. .PARAMETER Hostname [string] Name or IP address of the remote computer. Defaults to '.'. .PARAMETER Credential [PSCredential] Credential used to access the remote computer. .PARAMETER Path [string] Path to be tested. .EXAMPLE PS> Test-WMIRegistryKey -Path "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Something" True .INPUTS None .OUTPUTS $true, if the path exists $false, if the path does not exist $null, if the path could not be parsed. #> function Test-WMIRegistryKey { [CmdletBinding()] Param( [Parameter(Mandatory=$false)] [string]$Hostname = '.', [Parameter(Mandatory=$false)] [PSCredential]$Credential, [Parameter(Mandatory=$true)] [string]$Path ) $parsedPath = Parse-RegistryPath -Path $Path if ($null -eq $parsedPath) { return $null } $msPath = ('\\{0}\ROOT\DEFAULT:StdRegProv' -f $Hostname) $mScope = New-Object System.Management.ManagementScope($msPath) if ($null -ne $Credential) { $mScope.Options.Username = $Credential.UserName $mScope.Options.SecurePassword = $Credential.Password } try { $mScope.Connect() } catch { Write-Warning ('Error connecting management scope: {0}' -f $_.Exception.Message) return $null } $regObject = New-Object System.Management.ManagementClass($mScope, $msPath, $null) try { $res = $regObject.EnumKey($parsedPath.HiveKey, $parsedPath.Path) } catch { Write-Warning ('Error accessing key: {0}' -f $_.Exception.Message) return $null } if ($res.ReturnValue -ne 0) { return $false } else { return $true } } Export-ModuleMember -Function @('Test-WMIRegistryKey','New-WMIRegistryKey','Get-WMIRegistryValue','Set-WMIRegistryValue','Remove-WMIRegistryValue') |