Modules/WinRegOps/0.4.0/WinRegOps.psm1
#Region './Private/Get-OpenBaseKey.ps1' -1 <# .SYNOPSIS Opens a registry hive on the local computer. .DESCRIPTION This function opens a registry hive on the local computer using the Microsoft.Win32.RegistryKey::OpenBaseKey method. It allows you to specify the registry hive and view (32-bit or 64-bit). By default, it uses the local machine view. .PARAMETER RegistryHive Specifies the registry hive to open (e.g., HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER). .PARAMETER RegistryView Specifies the registry view to open (32-bit or 64-bit). Defaults to the system's default view (64-bit on a 64-bit OS, 32-bit on a 32-bit OS). .OUTPUTS Microsoft.Win32.RegistryKey The registry key object representing the opened registry hive. .EXAMPLE Get-OpenBaseKey -RegistryHive 'HKEY_LOCAL_MACHINE' Opens the HKEY_LOCAL_MACHINE hive on the local computer using the default registry view. .EXAMPLE Get-OpenBaseKey -RegistryHive 'HKEY_LOCAL_MACHINE' -RegistryView 'RegistryView32' Opens the HKEY_LOCAL_MACHINE hive on the local computer using the 32-bit view of the registry. .NOTES This function is a wrapper around the Microsoft.Win32.RegistryKey::OpenBaseKey method, providing an easier interface for opening registry hives locally. #> function Get-OpenBaseKey { param ( [Microsoft.Win32.RegistryHive]$RegistryHive, [Microsoft.Win32.RegistryView]$RegistryView = [Microsoft.Win32.RegistryView]::Default ) return [Microsoft.Win32.RegistryKey]::OpenBaseKey($RegistryHive, $RegistryView) } #EndRegion './Private/Get-OpenBaseKey.ps1' 39 #Region './Private/Get-OpenRemoteBaseKey.ps1' -1 <# .SYNOPSIS Opens a registry hive on a remote computer. .DESCRIPTION This function opens a registry hive on a remote computer using the Microsoft.Win32.RegistryKey::OpenRemoteBaseKey method. It allows you to specify the registry hive and the remote computer name. The remote computer must have the remote registry service running. .PARAMETER RegistryHive Specifies the registry hive to open (e.g., HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER). .PARAMETER ComputerName Specifies the name of the remote computer on which the registry hive will be opened. .OUTPUTS Microsoft.Win32.RegistryKey The registry key object representing the opened registry hive on the remote computer. .EXAMPLE Get-OpenRemoteBaseKey -RegistryHive 'HKEY_LOCAL_MACHINE' -ComputerName 'RemotePC' Opens the HKEY_LOCAL_MACHINE hive on the remote computer 'RemotePC'. .NOTES This function is a wrapper around the Microsoft.Win32.RegistryKey::OpenRemoteBaseKey method, providing an easier interface for opening registry hives on remote computers. The remote registry service must be enabled on the target machine. #> function Get-OpenRemoteBaseKey { param ( [Microsoft.Win32.RegistryHive]$RegistryHive, [string]$ComputerName ) return [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegistryHive, $ComputerName) } #EndRegion './Private/Get-OpenRemoteBaseKey.ps1' 34 #Region './Private/Get-RegistrySubKeyOperation.ps1' -1 <# .SYNOPSIS Prepares the registry subkey operation by opening the relevant registry key based on the parameter set. .DESCRIPTION This function prepares the environment for removing a registry subkey. It opens the correct registry key either by registry hive and path or by an existing registry key object, and returns the parent key and subkey name for further processing. .PARAMETER RegistryPath Specifies the path to the registry key to open. This is used only when the 'ByHive' parameter set is selected. .PARAMETER RegistryHive Specifies the registry hive where the key resides. This is used only when the 'ByHive' parameter set is selected. .PARAMETER ComputerName Specifies the name of the computer on which to perform the registry operation. This is used only when the 'ByHive' parameter set is selected. Defaults to the local machine if not specified. .PARAMETER ParentKey Specifies an existing registry key object from which to delete the subkey. This is used only when the 'ByKey' parameter set is selected. .PARAMETER SubKeyName Specifies the name of the subkey to delete. .PARAMETER ParameterSetName Specifies which parameter set is being used. It should be either 'ByHive' or 'ByKey'. .Outputs System.Collections.Hashtable .EXAMPLE $details = Get-RegistrySubKeyOperation -RegistryPath 'SOFTWARE\MyApp' -RegistryHive LocalMachine -ComputerName 'RemotePC' -ParameterSetName 'ByHive' This example prepares a registry operation on a remote computer by opening the 'SOFTWARE\MyApp' subkey in HKEY_LOCAL_MACHINE. .EXAMPLE $parentKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SOFTWARE\MyApp', $true) $details = Get-RegistrySubKeyOperation -ParentKey $parentKey -SubKeyName 'Settings' -ParameterSetName 'ByKey' This example prepares a registry operation by passing an already opened parent key and the subkey 'Settings'. #> function Get-RegistrySubKeyOperation { param ( [string]$RegistryPath, [Microsoft.Win32.RegistryHive]$RegistryHive, [string]$ComputerName, [Microsoft.Win32.RegistryKey]$ParentKey, [string]$SubKeyName, [string]$ParameterSetName ) if ($ParameterSetName -eq 'ByHive') { # Split path and get subkey name $parentPath = Split-Path -Path $RegistryPath -Parent $subKeyName = Split-Path -Path $RegistryPath -Leaf # Open the registry key try { $ParentKey = Open-RegistryKey -RegistryPath $parentPath -RegistryHive $RegistryHive -ComputerName $ComputerName -Writable $true } catch { throw "Failed to open registry key: $($RegistryHive)\$parentPath. $_" } return @{ ParentKey = $ParentKey; SubKeyName = $subKeyName } } elseif ($ParameterSetName -eq 'ByKey') { if ($null -eq $ParentKey) { throw [System.ArgumentNullException]::new("ParentKey cannot be null.") } return @{ ParentKey = $ParentKey; SubKeyName = $SubKeyName } } throw [System.ArgumentException]::new("Invalid parameter set.") } #EndRegion './Private/Get-RegistrySubKeyOperation.ps1' 82 #Region './Private/Invoke-DeleteSubkey.ps1' -1 <# .SYNOPSIS Deletes a specified subkey from the Windows registry. .DESCRIPTION The `Invoke-DeleteSubKey` function deletes a subkey from the Windows registry. It provides flexibility to either pass a registry hive and path or an existing registry key object to delete the subkey. It supports deleting subkeys on both local and remote computers. This function is used internally by the `Remove-RegistrySubKey` cmdlet to delete a subkey from the Windows registry. It is not intended to be used directly by end users. .PARAMETER ParentKey Specifies the parent registry key object from which to delete the subkey. .PARAMETER SubKeyName Specifies the name of the subkey to delete. .PARAMETER ThrowOnMissingSubKey Indicates whether the function should throw an error if the subkey to delete does not exist. If set to `$false`, no error will be thrown when attempting to delete a non-existent subkey. Defaults to `$true`. .INPUTS Microsoft.Win32.RegistryKey .OUTPUTS None .EXAMPLE $parentKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SOFTWARE\MyApp', $true) Invoke-DeleteSubKey -ParentKey $parentKey -SubKeyName 'Settings' This command deletes the 'Settings' subkey under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp' using the parent key object. .NOTES This function uses the .NET `Microsoft.Win32.RegistryKey` class to interact with the Windows registry. It is recommended to run this function with appropriate permissions, as registry edits may require elevated privileges. #> function Invoke-DeleteSubKey { param( [Microsoft.Win32.RegistryKey]$ParentKey, [string]$SubKeyName, [bool]$ThrowOnMissingSubKey = $true ) if ($ParentKey -eq $null) { throw [System.ArgumentNullException]::new("ParentKey cannot be null.") } if ([string]::IsNullOrEmpty($SubKeyName)) { throw [System.ArgumentNullException]::new("SubKeyName cannot be null or empty.") } try { if ($ThrowOnMissingSubKey) { $ParentKey.DeleteSubKey($SubKeyName, $true) } else { $ParentKey.DeleteSubKey($SubKeyName, $false) } } catch { throw $_ } } #EndRegion './Private/Invoke-DeleteSubkey.ps1' 74 #Region './Private/Invoke-DeleteSubKeyTree.ps1' -1 <# .SYNOPSIS Deletes a registry subkey and all of its child subkeys from the specified parent key. .DESCRIPTION The `Invoke-DeleteSubKeyTree` function deletes a specified subkey and all of its child subkeys from a provided registry key. It allows control over whether to throw an error if the subkey is missing. .PARAMETER ParentKey The parent registry key from which the subkey tree will be deleted. This parameter cannot be null. .PARAMETER SubKeyName The name of the subkey to delete, including all of its child subkeys. This parameter cannot be null or empty. .PARAMETER ThrowOnMissingSubKey Specifies whether an exception should be thrown if the subkey does not exist. Defaults to `$true`. .EXAMPLE $parentKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SOFTWARE\MyApp', $true) Invoke-DeleteSubKeyTree -ParentKey $parentKey -SubKeyName 'Settings' This command deletes the 'Settings' subkey and all its child subkeys under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp'. .EXAMPLE $parentKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('SOFTWARE\MyApp', $true) Invoke-DeleteSubKeyTree -ParentKey $parentKey -SubKeyName 'TempSettings' -ThrowOnMissingSubKey $false This command deletes the 'TempSettings' subkey and all its child subkeys under 'HKEY_CURRENT_USER\SOFTWARE\MyApp', and does not throw an exception if the subkey does not exist. .NOTES This function uses the .NET `Microsoft.Win32.RegistryKey` class to interact with the Windows registry. Ensure you have appropriate permissions to perform registry modifications. #> Function Invoke-DeleteSubKeyTree { param( [Microsoft.Win32.RegistryKey]$ParentKey, [string]$SubKeyName, [bool]$ThrowOnMissingSubKey = $true ) if ($null -eq $ParentKey) { throw [System.ArgumentNullException]::new("ParentKey cannot be null.") } if ([string]::IsNullOrEmpty($SubKeyName)) { throw [System.ArgumentNullException]::new("SubKeyName cannot be null or empty.") } try { if ($ThrowOnMissingSubKey) { $ParentKey.DeleteSubKeyTree($SubKeyName) } else { $ParentKey.DeleteSubKeyTree($SubKeyName, $false) } } catch { throw $_ } } #EndRegion './Private/Invoke-DeleteSubKeyTree.ps1' 70 #Region './Private/Invoke-RegCommand.ps1' -1 <# .SYNOPSIS Exports a specified registry key to a file using the `reg.exe` utility. .DESCRIPTION The `Invoke-RegCommand` function leverages the `reg.exe` command-line utility to export a specified registry key to a file. It accepts the registry path and export path as parameters, with default values provided by the environment variables `$ENV:Registry_Path` and `$ENV:Export_Path`. The function wraps this behavior in a PowerShell `Invoke-Command` call to execute the `reg.exe` command in the current session. .PARAMETER RegistryPath Specifies the path to the registry key that will be exported. If not provided, the function defaults to the value of the `$ENV:Registry_Path` environment variable. .PARAMETER ExportPath Specifies the file path where the registry export will be saved. If not provided, the function defaults to the value of the `$ENV:Export_Path` environment variable. .EXAMPLE Invoke-RegCommand -RegistryPath "HKCU\Software\MyKey" -ExportPath "C:\Export\mykey.reg" This example exports the registry key `HKCU\Software\MyKey` to the file `C:\Export\mykey.reg`. .EXAMPLE $ENV:Registry_Path = "HKLM\Software\MyApp" $ENV:Export_Path = "D:\Backup\myapp.reg" Invoke-RegCommand This example exports the registry key from the environment variable `Registry_Path` to the file path specified in `Export_Path`. .NOTES - The function requires the `reg.exe` utility, which is available on Windows operating systems by default. - The registry and export paths can be passed as parameters or set via environment variables. - Ensure the correct permissions are available for accessing the registry and writing to the specified output path. #> Function Invoke-RegCommand { param( [string]$RegistryPath = $ENV:Registry_Path, [string]$ExportPath = $ENV:Export_Path ) $Parameters = @{ Operation = 'EXPORT' Path = $RegistryPath OutputFile = $ExportPath } if (-not [string]::IsNullOrEmpty($Parameters.Path) -and -not [string]::IsNullOrEmpty($Parameters.OutputFile)) { $result = Invoke-Command -ScriptBlock { param($Parameters) ® $Parameters.Operation $Parameters.Path $Parameters.OutputFile } -ArgumentList $Parameters return $result } else { throw "Path or OutputFile is null or empty." } } #EndRegion './Private/Invoke-RegCommand.ps1' 60 #Region './Public/Backup-RegistryKey.ps1' -1 <# .SYNOPSIS Backs up a registry key from a specified computer to a backup file. .DESCRIPTION This function allows you to back up a registry key from a local or remote computer. It exports the registry key to a .reg file and saves it in the specified backup directory. It includes error handling for permission issues and remote access failures. .PARAMETER ComputerName The name of the computer from which the registry key will be backed up. Defaults to the local computer. .PARAMETER RegistryPath The full path of the registry key to be backed up. .PARAMETER BackupDirectory The directory where the backup file will be saved. Defaults to "C:\LHStuff\UserProfileTools\RegProfBackup". .EXAMPLE Backup-RegistryKey -RegistryPath 'HKLM\Software\MyApp' -BackupDirectory 'C:\Backups' Backs up the registry key 'HKLM\Software\MyApp' on the local computer to the 'C:\Backups' directory. .EXAMPLE Backup-RegistryKey -ComputerName 'RemotePC' -RegistryPath 'HKLM\Software\MyApp' 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' Backs up the registry key 'HKLM\Software\MyApp' from the remote computer 'RemotePC' to the default backup directory. .OUTPUTS System.Object .NOTES #> function Backup-RegistryKey { [outputType([System.Collections.Hashtable])] [CmdletBinding()] param ( [string]$ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory = $true)] [string]$RegistryPath, # Now dynamic, can back up any registry path [string]$BackupDirectory = $ENV:RegBackupDirectory ) # Determine if the operation is local or remote $isLocal = $ComputerName -eq $env:COMPUTERNAME # Generate the appropriate backup directory path (local or UNC) $backupDirectoryPath = Get-DirectoryPath -BasePath $BackupDirectory -ComputerName $ComputerName -IsLocal $isLocal # Ensure the backup directory exists locally or remotely Test-DirectoryExistence -Directory $backupDirectoryPath # Generate the backup file path with timestamp $backupPath = New-UniqueFilePath -Directory $backupDirectoryPath -Prefix "RegistryBackup" -Extension ".reg" # Get the full definition of Export-RegistryKey as a script block $exportRegistryFunction = Get-FunctionScriptBlock -FunctionName 'Export-RegistryKey' $scriptBlock = { param ($regExportPath, $registryPath, $exportFunction) # Load the Export-RegistryKey function & $exportFunction # Export the registry key return Export-RegistryKey -RegistryPath $registryPath -ExportPath $regExportPath } try { if ($isLocal) { # Local backup $backupResult = Export-RegistryKey -RegistryPath $RegistryPath -ExportPath $backupPath } else { # Remote backup using Invoke-Command $backupResult = Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptBlock ` -ArgumentList $backupPath, $RegistryPath, $exportRegistryFunction } # Return the result of the backup if ($backupResult.Success) { return @{ Success = $true BackupPath = $backupPath Message = "Registry key backed up successfully." ComputerName = $ComputerName } } else { Write-Error $backupResult.Message return @{ Success = $false BackupPath = $null Message = $backupResult.Message ComputerName = $ComputerName } } } catch { # Handle exceptions and return failure Write-Error "Failed to back up the registry key '$RegistryPath' on $ComputerName. Error: $_" return @{ Success = $false BackupPath = $null Message = "Failed to back up the registry key '$RegistryPath'. Error: $_" ComputerName = $ComputerName } } } #EndRegion './Public/Backup-RegistryKey.ps1' 116 #Region './Public/Export-RegistryKey.ps1' -1 <# .SYNOPSIS Exports a registry key to a .reg file. .DESCRIPTION This function exports a registry key to a specified file path. It can be run on a local or remote computer. The function uses the 'reg export' command to perform the export operation and returns the success status. .PARAMETER RegistryPath The full path of the registry key to be exported. .PARAMETER ExportPath The file path where the exported .reg file will be saved. .PARAMETER ComputerName The name of the computer from which the registry key will be exported. Defaults to the local computer. .EXAMPLE Export-RegistryKey -RegistryPath 'HKCU\Software\MyApp' -ExportPath 'C:\Backups\MyApp.reg' Exports the registry key 'HKCU\Software\MyApp' to 'C:\Backups\MyApp.reg'. .OUTPUTS System.Object .NOTES #> function Export-RegistryKey { param ( [string]$RegistryPath, # The registry path to be exported [string]$ExportPath, # The path where the backup .reg file will be saved [string]$ComputerName = $env:COMPUTERNAME # The name of the computer (local or remote) ) try { #$exportCommand = "reg export `"$RegistryPath`" `"$ExportPath`"" $result = Invoke-RegCommand -RegistryPath $RegistryPath -ExportPath $ExportPath #Invoke-Expression $exportCommand #$exportCommand = ® export $RegistryPath $ExportPath $null = $result if ($LASTEXITCODE -eq 0) { return @{ Success = $true BackupPath = $ExportPath Message = "Registry key '$RegistryPath' successfully backed up to '$ExportPath'." ComputerName = $ComputerName } } else { return @{ Success = $false BackupPath = $null Message = "Failed to export registry key '$RegistryPath'." ComputerName = $ComputerName } } } catch { return @{ Success = $false BackupPath = $null Message = "Error during registry export for key '$RegistryPath'. $_" ComputerName = $ComputerName } } } #EndRegion './Public/Export-RegistryKey.ps1' 73 #Region './Public/Get-RegistrySubKey.ps1' -1 <# .SYNOPSIS Retrieves a registry subkey from a given base key with various options for access control. .DESCRIPTION The Get-RegistrySubKey function is a wrapper for the .NET `Microsoft.Win32.RegistryKey.OpenSubKey` method. It allows retrieving a subkey with different access control settings, such as writable, permission checks, or registry rights, depending on the parameter set. The function uses three parameter sets: - BooleanSet: Opens a subkey with or without writable access. - PermissionCheckSet: Opens a subkey with a specific permission check option. - RightsSet: Opens a subkey with a specific access control right (e.g., ReadKey, WriteKey, or FullControl). .PARAMETER BaseKey The base registry key from which to open a subkey. This must be a valid `Microsoft.Win32.RegistryKey` object and is required in all parameter sets. It can be passed through the pipeline. .PARAMETER Name The name of the subkey to open. This parameter is required for all parameter sets. .PARAMETER Writable Specifies whether the subkey should be opened with writable access. This is only valid in the 'BooleanSet' parameter set. .PARAMETER PermissionCheck Specifies the type of permission check to use when opening the subkey. Valid values include: - Default: The default permission check. - ReadSubTree: Allows read-only access. - ReadWriteSubTree: Allows both read and write access. This parameter is only valid in the 'PermissionCheckSet' parameter set. .PARAMETER Rights Specifies the rights used to open the subkey. Valid values include: - ReadKey: Grants read access to the subkey. - WriteKey: Grants write access to the subkey. - FullControl: Grants full control (read and write) to the subkey. This parameter is only valid in the 'RightsSet' parameter set. .INPUTS Microsoft.Win32.RegistryKey You can pipe a `RegistryKey` object to the function as the BaseKey. .OUTPUTS Microsoft.Win32.RegistryKey The function returns the opened registry subkey if successful. .EXAMPLE # Example 1: Open a subkey with writable access $baseKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Software") Get-RegistrySubKey -BaseKey $baseKey -Name "MyApp" -Writable $true .Example # Example 2: Open a subkey with permission check (read-only access) $baseKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Software") Get-RegistrySubKey -BaseKey $baseKey -Name "MyApp" -PermissionCheck [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadSubTree .Example # Example 3: Open a subkey with specific rights (read access) $baseKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Software") Get-RegistrySubKey -BaseKey $baseKey -Name "MyApp" -Rights [System.Security.AccessControl.RegistryRights]::ReadKey .NOTES This function is designed to provide a PowerShell interface to interact with the .NET `RegistryKey` class, offering flexibility with different access control options. .LINK https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.registrykey?view=net-8.0 #> function Get-RegistrySubKey { [Alias("Open-RegistrySubKey")] [CmdletBinding(DefaultParameterSetName = 'DefaultSet')] param ( # Include 'BaseKey' in multiple sets and accept it from the pipeline [Parameter(Mandatory = $true, ParameterSetName = 'BooleanSet', ValueFromPipeline = $true)] [Parameter(Mandatory = $true, ParameterSetName = 'PermissionCheckSet', ValueFromPipeline = $true)] [Parameter(Mandatory = $true, ParameterSetName = 'RightsSet', ValueFromPipeline = $true)] [Microsoft.Win32.RegistryKey]$BaseKey, # 'Name' parameter belongs to all sets [Parameter(Mandatory = $true, ParameterSetName = 'BooleanSet')] [Parameter(Mandatory = $true, ParameterSetName = 'PermissionCheckSet')] [Parameter(Mandatory = $true, ParameterSetName = 'RightsSet')] [string]$Name, # 'writable' is only in the 'BooleanSet' [Parameter(Mandatory = $true, ParameterSetName = 'BooleanSet')] [ValidateSet([bool]$true, [bool]$false)] # Choices for bool parameters [bool]$writable, # 'permissionCheck' is only in the 'PermissionCheckSet' [Parameter(Mandatory = $true, ParameterSetName = 'PermissionCheckSet')] [ValidateSet([Microsoft.Win32.RegistryKeyPermissionCheck]::Default, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadSubTree, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree)] [Microsoft.Win32.RegistryKeyPermissionCheck]$permissionCheck, # 'rights' is only in the 'RightsSet' [Parameter(Mandatory = $true, ParameterSetName = 'RightsSet')] [ValidateSet([System.Security.AccessControl.RegistryRights]::ReadKey, [System.Security.AccessControl.RegistryRights]::WriteKey, [System.Security.AccessControl.RegistryRights]::FullControl)] [System.Security.AccessControl.RegistryRights]$rights ) process { try { switch ($PSCmdlet.ParameterSetName) { 'BooleanSet' { return $BaseKey.OpenSubKey($Name, $writable) } 'PermissionCheckSet' { return $BaseKey.OpenSubKey($Name, $permissionCheck) } 'RightsSet' { return $BaseKey.OpenSubKey($Name, $rights) } default { throw "Unknown parameter set: $($PSCmdlet.ParameterSetName)" } } } catch [System.Security.SecurityException] { $errorMessage = "SecurityException: Requested registry access is not allowed. Please check your permissions." throw [System.Security.SecurityException] $errorMessage } catch { throw } } } #EndRegion './Public/Get-RegistrySubKey.ps1' 141 #Region './Public/Get-RegistryValue.ps1' -1 <# .SYNOPSIS Retrieves a value from a specified registry key, with support for default values and options. .DESCRIPTION This function wraps the RegistryKey.GetValue method to retrieve a value from the Windows registry. You can supply a base registry key, the value name, an optional default value, and retrieval options. .PARAMETER BaseKey The base registry key from which to retrieve the value. This should be an open RegistryKey object. .PARAMETER ValueName The name of the registry value to retrieve. This is a required parameter. .PARAMETER DefaultValue An optional default value to return if the specified name is not found in the registry. If not provided, the method will return $null if the value name does not exist. .PARAMETER Options Optional retrieval options for the value. The available options are: - None: The default behavior. - DoNotExpandEnvironmentNames: Prevents the expansion of environment-variable strings. The default value for this parameter is [System.Registry.RegistryValueOptions]::None. .EXAMPLE $baseKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\MyApp") Get-RegistryValue -BaseKey $baseKey -ValueName "Setting1" Description: Retrieves the "Setting1" value from the "SOFTWARE\MyApp" registry key in the LocalMachine hive. .EXAMPLE $baseKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\MyApp") Get-RegistryValue -BaseKey $baseKey -ValueName "Setting1" -DefaultValue "DefaultValue" Description: Retrieves the "Setting1" value from the "SOFTWARE\MyApp" registry key. If the value does not exist, it returns "DefaultValue". .EXAMPLE $baseKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\MyApp") Get-RegistryValue -BaseKey $baseKey -ValueName "Setting1" -DefaultValue "DefaultValue" -Options [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames Description: Retrieves the "Setting1" value with the option to prevent expanding environment-variable strings. If the value does not exist, it returns "DefaultValue". .NOTES This function wraps around the .NET Framework's RegistryKey.GetValue method to make it easier to retrieve registry values in PowerShell. #> function Get-RegistryValue { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0)] [Microsoft.Win32.RegistryKey]$BaseKey, [Parameter(Mandatory = $true, Position = 1)] [string]$ValueName, [Parameter(Mandatory = $false, Position = 2)] [Object]$DefaultValue = $null, [Parameter(Mandatory = $false, Position = 3)] [Microsoft.Win32.RegistryOptions]$Options = [Microsoft.Win32.RegistryOptions]::None ) try { # Retrieve the registry value based on the provided options and default value if ($Options -ne [Microsoft.Win32.RegistryOptions]::None) { return $BaseKey.GetValue($ValueName, $DefaultValue, $Options) } elseif ($DefaultValue) { return $BaseKey.GetValue($ValueName, $DefaultValue) } else { return $BaseKey.GetValue($ValueName) } } catch [System.Security.SecurityException] { $errorMessage = "Access to the registry key is denied." throw [System.Security.SecurityException] $errorMessage } catch { throw $_ } } #EndRegion './Public/Get-RegistryValue.ps1' 95 #Region './Public/Get-RegistryValueKind.ps1' -1 <# .SYNOPSIS Retrieves the value kind (type) of a specified registry key value. .DESCRIPTION This function wraps the RegistryKey.GetValueKind method to retrieve the type (kind) of a registry value. You can supply a base registry key and the value name. It returns the type of the value (e.g., String, DWord, Binary). .PARAMETER BaseKey The base registry key from which to retrieve the value kind. This should be an open RegistryKey object. .PARAMETER ValueName The name of the registry value for which to retrieve the kind. This is a required parameter. .OUTPUTS Microsoft.Win32.RegistryValueKind The type of the value (e.g., String, DWord, Binary). .EXAMPLE $baseKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\MyApp") Get-RegistryValueKind -BaseKey $baseKey -ValueName "Setting1" Description: Retrieves the kind (type) of the "Setting1" value from the "SOFTWARE\MyApp" registry key. .NOTES This function wraps around the .NET Framework's RegistryKey.GetValueKind method to make it easier to retrieve registry value types in PowerShell. #> function Get-RegistryValueKind { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0)] [Microsoft.Win32.RegistryKey]$BaseKey, [Parameter(Mandatory = $true, Position = 1)] [string]$ValueName ) try { # Retrieve the kind (type) of the registry value return $BaseKey.GetValueKind($ValueName) } catch [System.Security.SecurityException] { $errorMessage = "Access to the registry key is denied." throw [System.Security.SecurityException] $errorMessage } catch { throw $_ } } #EndRegion './Public/Get-RegistryValueKind.ps1' 56 #Region './Public/Get-RegistryValueNames.ps1' -1 <# .SYNOPSIS Retrieves all the value names of a specified registry key. .DESCRIPTION This function wraps the RegistryKey.GetValueNames method to retrieve all the value names of a registry key. You can supply a base registry key, and the function will return an array of the value names present in the registry key. .PARAMETER BaseKey The base registry key from which to retrieve the value names. This should be an open RegistryKey object. .OUTPUTS String[] An array of strings representing the names of all the values stored in the registry key. .EXAMPLE $baseKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\MyApp") Get-RegistryValueNames -BaseKey $baseKey Description: Retrieves all the value names from the "SOFTWARE\MyApp" registry key. .NOTES This function wraps around the .NET Framework's RegistryKey.GetValueNames method to make it easier to retrieve value names in PowerShell. #> function Get-RegistryValueNames { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'The function name is appropriate.')] [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0)] [Microsoft.Win32.RegistryKey]$BaseKey ) try { # Retrieve all the value names in the registry key return $BaseKey.GetValueNames() } catch [System.Security.SecurityException] { $errorMessage = "Access to the registry key is denied." throw [System.Security.SecurityException] $errorMessage } catch { throw $_ } } #EndRegion './Public/Get-RegistryValueNames.ps1' 53 #Region './Public/New-RegistryKeyValuesObject.ps1' -1 <# .SYNOPSIS Creates a custom object representing the values of a registry key or subkey. .DESCRIPTION The New-RegistryKeyValuesObject function retrieves all the values of a specified registry key or subkey and returns a custom object containing the registry path, backup date, user, computer name, and the key's values. This function is flexible, allowing you to specify a subkey within the registry key, or work with the root key itself. Each value is stored along with its data type. .PARAMETER RegistryKey The base registry key to be queried. This parameter is mandatory and must be a valid `Microsoft.Win32.RegistryKey` object. .PARAMETER SubKeyName The name of the optional subkey within the `RegistryKey`. If provided, the function will operate on this subkey. If not provided, it will operate on the root registry key. .PARAMETER User The username of the individual performing the backup. Defaults to the current user's name from `$env:USERNAME`. .PARAMETER ComputerName The name of the computer where the registry key resides. Defaults to the current computer name from `$env:COMPUTERNAME`. .OUTPUTS PSCustomObject Returns a custom object with the following properties: - RegistryPath: The full path of the registry key or subkey. - BackupDate: The date and time of the backup. - ByUser: The username of the individual performing the backup. - ComputerName: The name of the computer. - Values: A dictionary of all the values within the registry key, where each entry contains: - Value: The data stored in the registry key value. - Type: The data type of the registry value (e.g., String, DWord, Binary). .EXAMPLE # Example 1: Export values from the root registry key $remoteRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, "RemotePC") $registryKey = $remoteRegistry.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList") $registryData = New-RegistryKeyValuesObject -RegistryKey $registryKey This example opens the `ProfileList` key on a remote computer and exports the values to a custom object. .EXAMPLE # Example 2: Export values from a specific subkey $remoteRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, "RemotePC") $registryKey = $remoteRegistry.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList") $registryData = New-RegistryKeyValuesObject -RegistryKey $registryKey -SubKeyName "S-1-5-21-12345" This example exports the values from a specific subkey (`S-1-5-21-12345`) within the `ProfileList` key on a remote computer. .NOTES - The function is useful for backing up registry data or auditing changes within a registry key. - Ensure that you have appropriate permissions to access the registry keys. .LINK https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.registrykey?view=net-8.0 #> function New-RegistryKeyValuesObject { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'No state changes are made in this function.')] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [Microsoft.Win32.RegistryKey]$RegistryKey, # Generic registry key [string]$SubKeyName, # Optional subkey name within the registry key [string]$User = $env:USERNAME, [string]$ComputerName = $env:COMPUTERNAME ) # Automatically set RegistryPath to the name of the registry key or subkey if provided if ($SubKeyName) { $subKey = Get-RegistrySubKey -BaseKey $RegistryKey -Name $SubKeyName -writable $false $RegistryPath = $subKey.Name $selectedKey = $subKey } else { $RegistryPath = $RegistryKey.Name $selectedKey = $RegistryKey } # Create the registry data object $registryData = [PSCustomObject]@{ RegistryPath = $RegistryPath BackupDate = Get-Date ByUser = $User ComputerName = $ComputerName Values = @{} } # Collect all value names and types from the subkey or root key foreach ($valueName in (Get-RegistryValueNames -baseKey $selectedKey)) { $value = Get-RegistryValue -BaseKey $selectedKey -ValueName $valueName $valueType = (Get-RegistryValueKind -BaseKey $selectedKey -ValueName $valueName).tostring() $registryData.Values[$valueName] = @{ Value = $value Type = $valueType } } return $registryData } #EndRegion './Public/New-RegistryKeyValuesObject.ps1' 108 #Region './Public/Open-RegistryKey.ps1' -1 <# .SYNOPSIS Opens a registry key on a local or remote computer. .DESCRIPTION This function opens a registry key on a local or remote computer. It returns the registry key object if successful, or $null if the key does not exist or access is denied. .PARAMETER RegistryPath The full path of the registry key to be opened. .PARAMETER RegistryHive The registry hive to open (e.g., HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER). Defaults to HKEY_LOCAL_MACHINE. .PARAMETER ComputerName The name of the computer where the registry key is located. Defaults to the local computer. .PARAMETER Writable Specifies whether the registry key should be opened with writable access. Defaults to $true. .EXAMPLE Open-RegistryKey -RegistryPath 'HKLM\Software\MyApp' Opens the registry key 'HKLM\Software\MyApp' on the local computer. .EXAMPLE Open-RegistryKey -RegistryPath 'Software\MyApp' -RegistryHive 'HKEY_CURRENT_USER' -ComputerName 'RemotePC' Opens the registry key 'Software\MyApp' under HKEY_CURRENT_USER on the remote computer 'RemotePC'. .OUTPUTS Microsoft.Win32.RegistryKey .NOTES This function uses helper functions Get-OpenBaseKey and Get-OpenRemoteBaseKey to abstract the static calls for opening registry keys locally or remotely. #> function Open-RegistryKey { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$RegistryPath, [Parameter(Mandatory = $false)] [Microsoft.Win32.RegistryHive]$RegistryHive = [Microsoft.Win32.RegistryHive]::LocalMachine, [Parameter(Mandatory = $false)] [string]$ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [bool]$Writable = $true ) try { # Determine if the operation is local or remote $isLocal = $ComputerName -eq $env:COMPUTERNAME $regKey = if ($isLocal) { Get-OpenBaseKey -RegistryHive $RegistryHive } else { Get-OpenRemoteBaseKey -RegistryHive $RegistryHive -ComputerName $ComputerName } } catch [System.Security.SecurityException] { $customError = "Access denied to registry hive '$RegistryHive' on '$ComputerName'. Ensure you have sufficient permissions." throw [System.Security.SecurityException] $customError } catch { Write-Error "Failed to open registry hive '$RegistryHive' on '$ComputerName'. Error: $_" return $null } try { # Open the subkey using Open-RegistrySubKey (alias for Get-RegistrySubKey) $openedKey = Open-RegistrySubKey -BaseKey $regKey -Name $RegistryPath -Writable $Writable if ($openedKey) { Write-Verbose "Successfully opened registry key at path '$RegistryPath' on '$ComputerName'." return $openedKey } else { Write-Warning "Registry key at path '$RegistryPath' not found on '$ComputerName'." return $null } } catch [System.Security.SecurityException] { $customError = "Access denied to registry SubKey '$RegistryPath' on '$ComputerName'. Ensure you have sufficient permissions." throw [System.Security.SecurityException] $customError } catch { Write-Error "Failed to open registry key at path '$RegistryPath' on '$ComputerName'. Error: $_" return $null } } #EndRegion './Public/Open-RegistryKey.ps1' 107 #Region './Public/Remove-RegistrySubKey.ps1' -1 <# .SYNOPSIS Removes a specified subkey from the Windows registry. .DESCRIPTION The `Remove-RegistrySubKey` cmdlet removes a subkey from the Windows registry. It provides flexibility to either pass a registry hive and path or an existing registry key object to delete the subkey. It supports deleting subkeys on both local and remote computers. .PARAMETER RegistryHive Specifies the registry hive where the key resides. This parameter is part of the 'ByHive' parameter set. Accepted values are: - ClassesRoot - CurrentUser - LocalMachine - Users - PerformanceData - CurrentConfig - DynData .PARAMETER RegistryPath Specifies the path to the registry key that contains the subkey to delete. This parameter is part of the 'ByHive' parameter set. .PARAMETER ComputerName Specifies the name of the computer on which to perform the registry operation. Defaults to the local machine if not specified. This parameter is part of the 'ByHive' parameter set. .PARAMETER ParentKey Specifies an existing registry key object from which to delete the subkey. This parameter is part of the 'ByKey' parameter set. .PARAMETER SubKeyName Specifies the name of the subkey to delete. This parameter is part of the 'ByKey' parameter set. .PARAMETER ThrowOnMissingSubKey Indicates whether the cmdlet should throw an error if the subkey to delete does not exist. If set to `$false`, no error will be thrown when attempting to delete a non-existent subkey. Defaults to `$true`. .EXAMPLE Remove-RegistrySubKey -RegistryHive LocalMachine -RegistryPath 'SOFTWARE\MyApp\Settings' This command deletes the 'Settings' subkey under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp' on the local machine. .EXAMPLE $parentKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SOFTWARE\MyApp', $true) Remove-RegistrySubKey -ParentKey $parentKey -SubKeyName 'Settings' This command deletes the 'Settings' subkey under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp' using the parent key object. .EXAMPLE Remove-RegistrySubKey -RegistryHive LocalMachine -RegistryPath 'SOFTWARE\MyApp\Settings' -ComputerName 'RemotePC' This command deletes the 'Settings' subkey under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp' on a remote computer named 'RemotePC'. .NOTES This function uses the .NET `Microsoft.Win32.RegistryKey` class to interact with the Windows registry. It is recommended to run this cmdlet with appropriate permissions, as registry edits may require elevated privileges. #> function Remove-RegistrySubKey { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High', DefaultParameterSetName = 'ByHive')] param ( # Parameter Set: ByHive [Parameter(Mandatory, ParameterSetName = 'ByHive')] [ValidateSet( [Microsoft.Win32.RegistryHive]::ClassesRoot, [Microsoft.Win32.RegistryHive]::CurrentUser, [Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryHive]::Users, [Microsoft.Win32.RegistryHive]::PerformanceData, [Microsoft.Win32.RegistryHive]::CurrentConfig, [Microsoft.Win32.RegistryHive]::DynData ) ] [Microsoft.Win32.RegistryHive]$RegistryHive, [Parameter(Mandatory, ParameterSetName = 'ByHive')] [string]$RegistryPath, [Parameter(ParameterSetName = 'ByHive')] [string]$ComputerName = $env:COMPUTERNAME, # Parameter Set: ByKey [Parameter(Mandatory, ParameterSetName = 'ByKey')] [Microsoft.Win32.RegistryKey]$ParentKey, [Parameter(Mandatory, ParameterSetName = 'ByKey')] [string]$SubKeyName, [Parameter(ParameterSetName = 'ByHive')] [Parameter(ParameterSetName = 'ByKey')] [bool]$ThrowOnMissingSubKey = $true ) begin { if ($PSCmdlet.ParameterSetName -eq "ByHive") { $params = @{ RegistryPath = $RegistryPath RegistryHive = $RegistryHive ComputerName = $ComputerName ParameterSetName = $PSCmdlet.ParameterSetName } } else { $params = @{ ParentKey = $ParentKey SubKeyName = $SubKeyName ParameterSetName = $PSCmdlet.ParameterSetName } } $operationDetails = Get-RegistrySubKeyOperation @params $ParentKey = $operationDetails.ParentKey $subKeyName = $operationDetails.SubKeyName if ([string]::IsNullOrEmpty($subKeyName)) { throw [System.ArgumentNullException]::new("SubKeyName cannot be null or empty.") } } process { if ($PSCmdlet.ShouldProcess("$($ParentKey.Name)\$subKeyName", "Removing registry subkey using DeleteSubKey")) { # Use DeleteSubKey method try { Invoke-DeleteSubKey -ParentKey $ParentKey -SubKeyName $subKeyName -ThrowOnMissingSubKey $ThrowOnMissingSubKey } catch { throw $_ } } } end { # If we opened the ParentKey internally, dispose of it if ($PSCmdlet.ParameterSetName -eq 'ByHive' -and $null -ne $ParentKey) { $ParentKey.Dispose() } } } #EndRegion './Public/Remove-RegistrySubKey.ps1' 150 #Region './Public/Remove-RegistrySubKeyTree.ps1' -1 <# .SYNOPSIS Recursively removes a specified subkey and all of its subkeys from the Windows registry. .DESCRIPTION The `Remove-RegistrySubKeyTree` cmdlet deletes a registry subkey and all of its child subkeys (if any) from the Windows registry. This cmdlet provides flexibility to either specify a registry hive and path, or pass an existing registry key object to delete the subkey tree. It supports deleting registry subkeys on both local and remote computers. .PARAMETER RegistryHive Specifies the registry hive where the key resides. This parameter is part of the 'ByHive' parameter set. Accepted values are: - ClassesRoot - CurrentUser - LocalMachine - Users - PerformanceData - CurrentConfig - DynData .PARAMETER RegistryPath Specifies the path to the registry key that contains the subkey to delete. This parameter is part of the 'ByHive' parameter set. .PARAMETER ComputerName Specifies the name of the computer on which to perform the registry operation. Defaults to the local machine if not specified. This parameter is part of the 'ByHive' parameter set. .PARAMETER ParentKey Specifies an existing registry key object from which to delete the subkey tree. This parameter is part of the 'ByKey' parameter set. .PARAMETER SubKeyName Specifies the name of the subkey to delete, including all of its child subkeys. This parameter is part of the 'ByKey' parameter set. .EXAMPLE Remove-RegistrySubKeyTree -RegistryHive LocalMachine -RegistryPath 'SOFTWARE\MyApp\Settings' This command deletes the 'Settings' subkey and all its child subkeys under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp' on the local machine. .EXAMPLE $parentKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SOFTWARE\MyApp', $true) Remove-RegistrySubKeyTree -ParentKey $parentKey -SubKeyName 'Settings' This command deletes the 'Settings' subkey and all its child subkeys under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp' using the parent key object. .EXAMPLE Remove-RegistrySubKeyTree -RegistryHive LocalMachine -RegistryPath 'SOFTWARE\MyApp\Settings' -ComputerName 'RemotePC' This command deletes the 'Settings' subkey and all its child subkeys under 'HKEY_LOCAL_MACHINE\SOFTWARE\MyApp' on a remote computer named 'RemotePC'. .NOTES This function uses the .NET `Microsoft.Win32.RegistryKey` class to interact with the Windows registry. Registry operations can be sensitive, and it is recommended to run this cmdlet with appropriate permissions (e.g., as an Administrator) to avoid access issues. #> function Remove-RegistrySubKeyTree { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High", DefaultParameterSetName = 'ByHive')] param ( # Parameter Set: ByHive [Parameter(Mandatory, ParameterSetName = 'ByHive')] [ValidateSet( [Microsoft.Win32.RegistryHive]::ClassesRoot, [Microsoft.Win32.RegistryHive]::CurrentUser, [Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryHive]::Users, [Microsoft.Win32.RegistryHive]::PerformanceData, [Microsoft.Win32.RegistryHive]::CurrentConfig, [Microsoft.Win32.RegistryHive]::DynData ) ] [Microsoft.Win32.RegistryHive]$RegistryHive, [Parameter(Mandatory, ParameterSetName = 'ByHive')] [string]$RegistryPath, [Parameter(ParameterSetName = 'ByHive')] [string]$ComputerName = $env:COMPUTERNAME, # Parameter Set: ByKey [Parameter(Mandatory, ParameterSetName = 'ByKey')] [Microsoft.Win32.RegistryKey]$ParentKey, [Parameter(Mandatory, ParameterSetName = 'ByKey')] [string]$SubKeyName ) begin { if ($PSCmdlet.ParameterSetName -eq "ByHive") { $params = @{ RegistryPath = $RegistryPath RegistryHive = $RegistryHive ComputerName = $ComputerName ParameterSetName = $PSCmdlet.ParameterSetName } } else { $params = @{ ParentKey = $ParentKey SubKeyName = $SubKeyName ParameterSetName = $PSCmdlet.ParameterSetName } } $operationDetails = Get-RegistrySubKeyOperation @params $ParentKey = $operationDetails.ParentKey $subKeyName = $operationDetails.SubKeyName if ([string]::IsNullOrEmpty($subKeyName)) { throw [System.ArgumentNullException]::new("SubKeyName cannot be null or empty.") } } process { if ($PSCmdlet.ShouldProcess("$($ParentKey.Name)\$subKeyName", "Removing registry subkey tree")) { # Call Invoke-DeleteSubKeyTree to handle the deletion Invoke-DeleteSubKeyTree -ParentKey $ParentKey -SubKeyName $subKeyName -ThrowOnMissingSubKey $true Write-Verbose "SubKey '$subKeyName' and its child subkeys deleted using DeleteSubKeyTree." } } end { # If we opened the ParentKey internally, dispose of it if ($PSCmdlet.ParameterSetName -eq 'ByHive' -and $null -ne $ParentKey) { $ParentKey.Dispose() } } } #EndRegion './Public/Remove-RegistrySubKeyTree.ps1' 133 |