WinRegistry.psm1
$ErrorActionPreference = 'Stop' $hives = @{ 'HKCR' = 'HKEY_CLASSES_ROOT'; 'HKCU' = 'HKEY_CURRENT_USER'; 'HKLM' = 'HKEY_LOCAL_MACHINE'; 'HKU' = 'HKEY_USERS'; 'HKCC' = 'HKEY_CURRENT_CONFIG' } $types = @{ 'REG_SZ' = 'STRING'; 'REG_EXPAND_SZ' = 'EXPANDSTRING'; 'REG_MULTI_SZ' = 'MULTISTRING'; 'REG_DWORD' = 'DWORD'; 'REG_QWORD' = 'QWORD'; 'REG_BINARY' = 'BINARY' } $registryDrives = (Get-PSDrive | Where-Object { $_.Provider.name -eq 'Registry' }).Name foreach ($hive in $hives.Keys) { if ($hive -notin $registryDrives) { New-PSDrive -Name $hive -PSProvider Registry -Root $hives.$hive | Out-Null } } #-------------------------------------------------- function Convert-RegPath { param( [Parameter(Position = 0, ValueFromPipeline = $true)] [AllowEmptyString()] [string]$RegPath ) process { # replace slashes with backslashes $RegPath = $RegPath.Replace('/', '\') # remove prefix 'Computer' $RegPath = $RegPath -replace '^Computer\\', '' # replace long-formatted name with abbreviation if ($RegPath.StartsWith('HKEY_')) { if ($RegPath -match '(^HKEY_[a-zA-Z_]+)\\') { $hiveLongName = $Matches[1] $hive = ($hives.GetEnumerator() | ` Where-Object { $_.value -eq $hiveLongName }).name $RegPath = $RegPath.Replace($hiveLongName, $hive) } } # convert to PS provider path foreach ($hive in $hives.Keys) { if ($RegPath.ToUpper().StartsWith($hive)) { # only Registry-specific paths are validated $regPathValidated = $true if ($RegPath -notmatch '^[a-zA-Z]+:\\\.*') { $RegPath = $RegPath -replace "^$hive", "$hive`:" } break } } if (!$regPathValidated) { throw "Failed to convert path `"$RegPath`"" } # send result to pipeline $RegPath } <# .Description Converts Registry path into format supported by PowerShell provider. This is internal function and is not exported on module import. .PARAMETER RegPath Specifies full path to the target Registry key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } #-------------------------------------------------- function New-RegKey { param ( [Parameter(Position = 0, Mandatory = $true)] [string]$RegPath, [Parameter(Position = 1)] [switch]$Force ) if (!$Force) { throw "Parameter -Force is required to confirm this operation." } $RegPath = Convert-RegPath $RegPath $paths = @() while (!(Test-Path $RegPath)) { $paths += , $RegPath $RegPath = $RegPath | Split-Path } try { $paths[($paths.Length - 1)..0] | ` ForEach-Object { New-Item $_ | Out-Null } } catch { if ($_.Exception -like "*Requested registry access is not allowed*") { throw "Access denied. Are you running as administrator?" } throw $_ } <# .Description Creates new Registry key, if it does not exist already. Automatically creates missing subkeys in the path. .PARAMETER RegPath Specifies full path to the target Registry key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .PARAMETER Force Required parameter. Use to confirm your intent to proceed. Example: -Force .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } #-------------------------------------------------- function Show-RegKey { param ( [Parameter(Position = 0, Mandatory = $true)] [string]$RegPath, [Parameter(Position = 1)] [switch]$SubKeys ) $RegPath = Convert-RegPath $RegPath if ($SubKeys) { $keys = (Get-ChildItem $RegPath).name | ` Sort-Object | Split-Path -Leaf $keys } else { $keys = (Get-ChildItem $RegPath).name | Sort-Object $properties = (Get-Item $RegPath).property | Sort-Object $keys $properties } <# .Description Lists subkeys (with full paths) and properties of the target Registry key. Optionally only lists subkeys names. .PARAMETER RegPath Specifies full path to the target Registry Key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .PARAMETER SubKeys Only lists subkeys names of the target Registry key. Example: -SubKeys .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } #-------------------------------------------------- function Get-RegKeyProperties { param ( [Parameter(Position = 0, Mandatory = $true)] [string]$RegPath, [Parameter(Position = 1)] [string]$Filter = '*', [Parameter(Position = 2)] [switch]$Detailed, [Parameter(ParameterSetName = "detailed", Position = 3)] [ValidateScript({ if (!$Detailed) { throw "Parameter -AsHashtable can only be used after -Detailed." } $true })] [switch]$AsHashtable ) $RegPath = Convert-RegPath $RegPath $propNames = (Get-Item $RegPath).property | ` Where-Object { $_ -like $Filter } | Sort-Object $propNameMaxLength = ($propNames | ` ForEach-Object { $_.length } | Measure-Object -Maximum).Maximum # return only properties names if (!$Detailed) { return $propNames } $properties = [ordered]@{} foreach ($prop in $propNames) { $propValue = Get-ItemProperty $RegPath | Select-Object -ExpandProperty $prop $propType = ([string](Get-Item $RegPath).getvaluekind($prop)).toUpper() $properties.Add($prop, @{ 'value' = $propValue; 'type' = $propType }) } # return null if no properties found if ($properties.Count -eq 0) { return $null } # return results as hashtable if ($AsHashtable) { return $properties } # return results as array of formatted strings if ($propNameMaxLength -gt 36) { $propNameMaxLength = 36 } $spacing = " " * 4 $padName = $propNameMaxLength $padType = 12 $output = @('Name'.PadRight($padName), 'Type'.PadRight($padType), 'Value' -join $spacing) $output += , ('----'.PadRight($padName), '----'.PadRight($padType), '----' -join $spacing) foreach ($prop in $properties.keys) { $propName = $prop if ($propName.length -gt $padName) { $propName = $propName.SubString(0, $padName - 3) + '...' } $output += , ($propName.PadRight($padName), $properties.$prop.type.PadRight($padType), $properties.$prop.value -join $spacing) } return $output <# .Description Lists properties of the target Registry key. Accepts filters. Optionally shows properties' values and types. Optionally returns result set as hashtable. .PARAMETER RegPath Specifies full path to the target Registry Key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .PARAMETER Filter Specifies filter for properties names to be included into result set. Example: -Filter propname* .PARAMETER Detailed Includes properties' values and types. Example: -Detailed .PARAMETER AsHashtable Returns result set as hashtable. Requires parameter -Detailed to be specified first (must appear before -AsHashtable). Example: -AsHashtable .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } #-------------------------------------------------- function Get-RegKeyPropertyValue { param ( [Parameter(Position = 0, Mandatory = $true)] [string]$RegPath, [parameter(Position = 1, Mandatory = $true)] [string]$Property, [parameter(Position = 2)] [switch]$GetType ) $RegPath = Convert-RegPath $RegPath # return property value type if ($GetType) { $valueType = ([string](Get-Item $RegPath).getvaluekind($Property)).toUpper() if ($valueType -notin $types.Values) { throw "Uncknown value type `"$valueType`"." } return $valueType } # return property value $value = Get-ItemProperty $RegPath | Select-Object -ExpandProperty $Property return $value <# .Description Returns value of specific Registry key property. Optionally returns property type instead of value. .PARAMETER RegPath Specifies full path to the target Registry Key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .PARAMETER Property Specifies target Registry key property. Example: -Property <property_name> .PARAMETER GetType Returns property type instead of value. Example: -GetType .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } #-------------------------------------------------- function Set-RegKeyPropertyValue { param ( [parameter(Position = 0, Mandatory = $true)] [string]$RegPath, [parameter(Position = 1, Mandatory = $true)] [string]$Property, [parameter(Position = 2)] [string]$Value = $null, [parameter(Position = 3)] [ValidateSet('STRING', 'EXPANDSTRING', 'MULTISTRING', 'DWORD', 'QWORD', 'BINARY', 'REG_SZ', 'REG_EXPAND_SZ', 'REG_MULTI_SZ', 'REG_DWORD', 'REG_QWORD', 'REG_BINARY', $null)] [string]$ValueType = $null, [parameter()] [switch]$Force ) if (!$Force) { throw "Parameter -Force is required to confirm this operation." } $RegPath = Convert-RegPath $RegPath $UserInputValueType = $ValueType # if value type not explicitly specified, then check current type (if target property exists) if (!$ValueType) { try { $ValueType = Get-RegKeyPropertyValue $RegPath $Property -GetType } catch {} } # set default value type if (!$ValueType) { $ValueType = 'STRING' } # convert type name into PowerShell-accepted format if ($ValueType.StartsWith('REG_')) { $ValueType = $types.$ValueType } # create missing children directories in $RegPath New-RegKey $RegPath -Force:$Force # create key property with value try { New-ItemProperty $RegPath -Name $Property -PropertyType $ValueType -Value $Value -Force | Out-Null } catch { if ($_.Exception -like "*Cannot convert value * to type*") { if ($UserInputValueType) { throw "Value `"$Value`" cannot be converted into type `"$ValueType`"." } else { $currentType = Get-RegKeyPropertyValue $RegPath -Property $Property -GetType throw "Value `"$Value`" cannot be converted into target property's current type `"$currentType`" (use -ValueType parameter to force change type)." } } if ($_.Exception -like "*Requested registry access is not allowed*") { throw "Access denied. Are you running as administrator?" } throw $_ } <# .Description Sets value and type of specific Registry key property. Creates new property, if does not exist already. If type is not specified, uses current type of the target property (value must be of the same type). If type is not specified and property does not not exist, defaults to 'REG_SZ'. .PARAMETER RegPath Specifies full path to the target Registry Key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .PARAMETER Property Specifies target Registry key property. Example: -Property <property_name> .PARAMETER Value Specifies new value. Example: -Value <value> .PARAMETER ValueType Specifies new value type. CAUTION: if specified while target property exists, will force-udate of property type. If not specified while target property exists, will use current property type. Example: -ValueType DWORD .PARAMETER Force Required parameter. Use to confirm your intent to proceed. Example: -Force .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } #-------------------------------------------------- function Remove-RegKey { param( [Parameter(Position = 0, Mandatory = $true)] [string]$RegPath, [Parameter(Position = 1)] [switch]$Force ) if (!$Force) { throw "Parameter -Force is required to confirm this operation." } $RegPath = Convert-RegPath $RegPath try { Remove-Item $RegPath -Force:$Force -Recurse } catch { if ($_.Exception -like "*Requested registry access is not allowed*") { throw "Access denied. Are you running as administrator?" } throw $_ } <# .Description Deletes target Registry key and all its children (subkeys and properties). .PARAMETER RegPath Specifies full path to the target Registry Key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .PARAMETER Force Required parameter. Use to confirm your intent to proceed. Example: -Force .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } #-------------------------------------------------- function Remove-RegKeyProperty { param( [Parameter(Position = 0, Mandatory = $true)] [string]$RegPath, [parameter(Position = 1, Mandatory = $true)] [string]$Property, [Parameter(Position = 2)] [switch]$Force ) if (!$Force) { throw "Parameter -Force is required to confirm this operation." } $RegPath = Convert-RegPath $RegPath try { Remove-ItemProperty $RegPath -Name $Property -Force:$Force } catch { if ($_.Exception -like "*Requested registry access is not allowed*") { throw "Access denied. Are you running as administrator?" } throw $_ } <# .Description Deletes specific Registry key property. .PARAMETER RegPath Specifies full path to the target Registry Key. Example: -RegPath Computer\HKEY_LOCAL_MACHINE\SOFTWARE\<some_key> Example: -RegPath HKLM/SOFTWARE/<some_key> .PARAMETER Property Specifies target Registry key property. Example: -Property <property_name> .PARAMETER Force Required parameter. Use to confirm your intent to proceed. Example: -Force .LINK https://github.com/PavelStsefanovich/lib_powershell/tree/main/modules/WinRegistry #> } Export-ModuleMember -Function New-RegKey, Show-RegKey, Get-RegKeyProperties, Get-RegKeyPropertyValue, Set-RegKeyPropertyValue, Remove-RegKey, Remove-RegKeyProperty |