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/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)
            &reg $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 = "C:\LHStuff\UserProfileTools\RegProfBackup"
    )

    # 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 = &reg 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' 77
#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/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 subkey from a registry key.

.DESCRIPTION
This function deletes a subkey from a specified parent registry key. It supports the -WhatIf and -Confirm parameters for safety.

.PARAMETER ParentKey
The parent registry key object.

.PARAMETER SubKeyName
The name of the subkey to be deleted.

.PARAMETER ComputerName
The name of the computer where the registry subkey is located. Defaults to the local computer.

.EXAMPLE
$key = Open-RegistryKey -RegistryPath 'HKLM\Software'
Remove-RegistrySubKey -ParentKey $key -SubKeyName 'MyApp'

Deletes the subkey 'MyApp' under the registry key 'HKLM\Software' on the local computer.

.EXAMPLE
$key = Open-RegistryKey -RegistryPath 'HKLM\Software'
Remove-RegistrySubKey -ParentKey $key -SubKeyName 'MyApp' -WhatIf

Shows what would happen if the subkey 'MyApp' were deleted, without actually performing the deletion.

.OUTPUTS
System.Boolean

.NOTES

#>

function Remove-RegistrySubKey
{
    [outputType([system.Boolean])]
    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
    param (
        [Parameter(Mandatory = $true)]
        [Microsoft.Win32.RegistryKey]$ParentKey, # The parent registry key
        [string]$SubKeyName, # The subkey to be deleted
        [string]$ComputerName = $env:COMPUTERNAME # Default to local computer
    )

    try
    {
        # Ensure ShouldProcess is used for safety with -WhatIf and -Confirm support
        if ($PSCmdlet.ShouldProcess("Registry subkey '$SubKeyName' on $ComputerName", "Remove"))
        {
            # Proceed with deletion
            $ParentKey.DeleteSubKeyTree($SubKeyName)
            Write-Verbose "Successfully removed registry subkey '$SubKeyName' on $ComputerName."
            return $true
        }
        else
        {
            # ShouldProcess returned false, so nothing is done
            Write-Verbose "Operation to remove registry subkey '$SubKeyName' on $ComputerName was skipped."
            return $false
        }

    }
    catch
    {
        Write-Error "Failed to remove the registry subkey '$SubKeyName' on $ComputerName. Error: $_"
        return $false
    }
}
#EndRegion './Public/Remove-RegistrySubKey.ps1' 70