Get-RegistryKey.ps1

<#PSScriptInfo
.VERSION 1.0.2
 
.GUID 3db94b5b-3f5c-46b5-b382-0e1ed1eb18e1
 
.AUTHOR /u/Pyprohly
 
.TAGS Registry
 
.RELEASENOTES
    1.0.2 | 2018-11-12
        Add more registry hives
 
    1.0 | 2018-11-12
        Initial release
 
.DESCRIPTION
    Returns a read and writable Microsoft.Win32.RegistryKey object.
 
    The RegistryKey object that is returned by Get-Item isn’t open for writing.
    This cmdlet returns a RegistryKey object that is writable.
 
    No object is returned if the specified key could not be found or opened.
#>


param(
    [Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Alias('PSPath', 'KeyName')]
    [string]
    $Path,

    [Microsoft.Win32.RegistryKeyPermissionCheck]
    $PermissionCheck = [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,

    [System.Security.AccessControl.RegistryRights]
    [Alias('Rights')]
    $RegistryRights = [System.Security.AccessControl.RegistryRights]'ReadKey,WriteKey'
)

function Get-RegistryKey {
    [CmdletBinding()]
    [OutputType('Microsoft.Win32.RegistryKey')]
    param(
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Alias('PSPath', 'KeyName')]
        [string]
        $Path,

        [Microsoft.Win32.RegistryKeyPermissionCheck]
        $PermissionCheck = [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,

        [System.Security.AccessControl.RegistryRights]
        [Alias('Rights')]
        $RegistryRights = [System.Security.AccessControl.RegistryRights]'ReadKey,WriteKey'
    )

    begin {
        $hives = @{
            hkcr = [Microsoft.Win32.Registry]::ClassesRoot
            hkcu = [Microsoft.Win32.Registry]::CurrentUser
            hklm = [Microsoft.Win32.Registry]::LocalMachine
            hku  = [Microsoft.Win32.Registry]::Users
            hkcc = [Microsoft.Win32.Registry]::CurrentConfig
            hkdd = [Microsoft.Win32.Registry]::DynData
        }

        $provider = Get-PSProvider -PSProvider Registry
        $providerString = $provider.ToString()

        foreach ($hive in $hives.GetEnumerator()) {
            $null = New-PSDrive -Name $hive.Name.ToUpper() -PSProvider Registry -Root $hive.Value.Name -ErrorAction SilentlyContinue
        }
    }

    process {
        foreach ($key in $Path) {
            if ($key.StartsWith($providerString)) {
                $key = $key.Substring($providerString.Length).TrimStart(':')
            } elseif ($key.StartsWith($provider.Name)) {
                $key = $key.Substring($provider.Name.Length).TrimStart(':')
            }

            $rh = $rk = $null
            :outer foreach ($rootKey in $hives.GetEnumerator()) {
                $rh = $rootKey.Value
                foreach ($prefix in ($rootKey.Name, $rootKey.Value.Name)) {
                    if ($key.StartsWith($prefix, [System.StringComparison]::OrdinalIgnoreCase)) {
                        $rk = $key.Substring($prefix.Length).TrimStart(':\')
                        break outer
                    }
                }
            }
            if (!$rk) { return }

            $o = $rh.OpenSubKey($rk, $PermissionCheck, $RegistryRights)
            if (!$o) { return }

            [string[]]$keyValueNames = try {
                $o.GetValueNames()
            } catch [System.UnauthorizedAccessException] {
                New-Object string[] 0
            }

            $rootName, $keyName = $o.Name.Split('\')[0,-1]
            $keyPath = $o.Name.Substring(0, $o.Name.LastIndexOf('\'))
            $o | Add-Member -PassThru -MemberType NoteProperty -Name Property -Value $keyValueNames |
                    Add-Member -PassThru -MemberType NoteProperty -Name PSChildName -Value $keyName |
                    Add-Member -PassThru -MemberType NoteProperty -Name PSDrive -Value (
                        Get-PSDrive -PSProvider Registry | Where-Object Root -eq $rootName) |
                    Add-Member -PassThru -MemberType NoteProperty -Name PSIsContainer -Value $true |
                    Add-Member -PassThru -MemberType NoteProperty -Name PSParentPath -Value (
                        $providerString + '::' + $keyPath) |
                    Add-Member -PassThru -MemberType NoteProperty -Name PSPath -Value (
                        $providerString + '::' + $o.Name) |
                    Add-Member -PassThru -MemberType NoteProperty -Name PSProvider -Value $provider
        }
    }
}

if ($MyInvocation.InvocationName -ne '.') {
    if ($MyInvocation.ExpectingInput) {
        $null = $PSBoundParameters.Remove('Path')
        $input | Get-RegistryKey @PSBoundParameters
    } else {
        Get-RegistryKey @PSBoundParameters
    }
}