Search Registry for Entry Names

Posted by : on

Category : powershell   scripts   registry


Introduction </h3>

This is a small function to search in the registry recursively for all entries matching a specified name. Using this information, you can replace all the values found. This post also contains a function to add registry values in a specified path to test the search function.


Search Registry Recursively </h3>

    function Test-RegistryValue{
        param (
            [Parameter(Mandatory = $true, Position=0)]
            [String]$Path,
            [Parameter(Mandatory = $true, Position=1)]
            [Alias('Entry')]
            [ValidateNotNullOrEmpty()]$Name
        )

        if(-not(Test-Path $Path)){
            return $false
        }
        $props = Get-ItemProperty -Path $Path -ErrorAction Ignore
        if($props -eq $Null){return $False}
        $value =  $props.$Name
        if($null -eq $value -or $value.Length -eq 0) { return $false }

        return $true
       
    }



    function Get-EntriesRecursively {
    <#
        .Synopsis
         Get the list of entries recursively from the registry
        .Description
        Get the list of entries recursively from the registry, given a property name and root path
        .Parameter Path
         Registry path
        .Parameter Name
        The entry name to search
    #>
        [CmdletBinding(SupportsShouldProcess)]
        param (
         [parameter(Mandatory=$true)]
         [string]$Path,
         [parameter(Mandatory=$true)]
         [string]$Name,
         [parameter(Mandatory=$false)]
         [System.Collections.ArrayList]$Results
        )
        
        try{
            $CurrentDepth = 1
            if($Results -eq $Null){
                Set-Variable -Name "RegRoot" -Value "$Path" -Scope Global -ErrorAction Ignore
                $Results = [System.Collections.ArrayList]::new()
            }else{
                $CurrentDepth = [regex]::matches($($Path.Replace($(Get-Variable -Name "RegRoot" -ValueOnly),'')),"\\").Count
            }
            $AllChilds=(Get-Item "$Path\*").PSChildName
            $AllChildsCount=$AllChilds.Count
            if($AllChildsCount -gt 0){
                $Spaces = '    '
                For($i = 0 ; $i -lt $CurrentDepth ; $i++){$Spaces += '    '}   
                Write-Verbose "$Spaces|---| + $AllChildsCount subkey in $Path"
            }
            foreach($Entry in $AllChilds){
                $exists=Test-RegistryValue "$Path\$Entry" "$Name"
                if($exists){
                    $Value=(Get-ItemProperty "$Path\$Entry")."$Name"
                    Write-Verbose "    $Spaces---> Found $Name [$Value]"
                    [pscustomobject]$o = @{
                        Path = "$Path\$Entry"
                        Name = $Name
                        Value = $Value
                    }

                    $Null = $Results.Add($o)    
                }

                $c = (Get-Item "$Path\$Entry\*").Count
                if($c -gt 0){
                    $Null = Get-EntriesRecursively -Path "$Path\$Entry" -Name $Name -Results $Results
                }
            }

            return $Results
            
        }catch{
            Write-Error "$_"

        }
    }

New-TestEntries </h3>

In order to test the search function above, this helper function will be useful :

     
    [CmdletBinding(SupportsShouldProcess)]
        param (
            [parameter(Mandatory=$false)]
            [string]$Path = "HKCU:\SOFTWARE\DevelopmentSandbox\TestSettings",
            [parameter(Mandatory=$false)]
            [int]$NumEntries = 10,
            [parameter(Mandatory=$false)]
            [int]$MaxDepth = 5,
            [parameter(Mandatory=$false)]
            [switch]$BogusEntries,
            [parameter(Mandatory=$false)]
            [switch]$Test,
            [parameter(Mandatory=$false)]
            [switch]$StartRegEd
        )

    try{

        $TestMode = $False        
        if ( ($PSBoundParameters.ContainsKey('WhatIf') -Or $Test) ){         
            $TestMode = $True
        }

        $TotalEntries = 0
        Write-Host "Root Path " -f Red -n ; Write-Host "[$Path]" -f Gray
        New-Item -Path $Path -ItemType 'Directory' -Force  -ErrorAction Ignore | Out-null

        Get-Random -SetSeed $(Get-Date -UFormat %s) | Out-null
        $p = '' 
        $Noise = [System.Collections.ArrayList]::new()
        $DepthValues = Get-Random -Maximum $MaxDepth -Minimum 1 -Count $numEntries
        ForEach($Depth in $DepthValues){
            $p = $Path
            $rel = '/'
            [string]$s = (New-Guid).Guid 
            [string[]]$sa = $s.Split('-') 
            # valid use?
            For($j = 0 ; $j -lt $Depth ; $j++){
                $p = Join-Path $p $sa[$j]
                $rel = Join-Path $rel $sa[$j]

                if($BogusEntries){
                    $n1 = "Guid_$j"
                    $n2 = "Date_$j"
                    $v1 = $((New-Guid).Guid)
                    $v2 = $((Get-Date).GetDateTimeFormats()[$j])

                    if(-not $TestMode){
                        New-Item -Path $p -Force | Out-null
                        New-ItemProperty -Path $p -Name $n1 -Value $v1 -PropertyType 'String'  | Out-null
                        New-ItemProperty -Path $p -Name $n2 -Value $v2 -PropertyType 'String'  | Out-null

                        Write-Verbose "`t+$p"
                        Write-Verbose "`t===> $n1 / $v1"
                        Write-Verbose "`t===> $n2 / $v2"
                        $Null = $Noise.Add(@{
                            Path = $p
                            Name = $n1
                            Value = $v1
                        })
                        $Null = $Noise.Add(@{
                            Path = $p
                            Name = $n2
                            Value = $v2
                        })                  
                    }else{
                        Write-Host -n -f DarkRed "[TestMode] "
                        Write-Host -n -f Gray "$p"
                        Write-Host -f DarkYellow "/[$n1;$v1]"
                    }
                }
            }

            $Name   = 'IP Address'
            $Type   = 'String'
            $Value  = "" ; 

            $r = Get-Random -Maximum 4 -Minimum 1
            switch($r){
                1  {$Value = "192.168.$(Get-Random -Maximum 255 -Minimum 1).$(Get-Random -Maximum 255 -Minimum 1)" ; }
                2  {$Value = "$(Get-Random -Maximum 99 -Minimum 1).$(Get-Random -Maximum 99 -Minimum 1).$(Get-Random -Maximum 255 -Minimum 1).$(Get-Random -Maximum 255 -Minimum 1)" ; }
                3  {$Value = "10.0.$(Get-Random -Maximum 100 -Minimum 1).$(Get-Random -Maximum 255 -Minimum 1)" ; }
            }
            
            if(-not $TestMode){
                New-Item -Path $p -Force | Out-null
                New-ItemProperty -Path $p -Name $Name -Value $Value -PropertyType $Type  | Out-null
                
                Write-Host "+ $Name / " -n -f Blue
                Write-Host "$Value" -n -f Yellow
                Write-Host "`t`t[$rel]" -f Gray
           }else{
                Write-Host -n -f DarkRed "[TestMode] "
                Write-Host -n -f Gray "$p"
                Write-Host -f DarkYellow "/[$Name;$Value]"
            }
            $TotalEntries++
        }

        Write-Host -f DarkCyan "+ IPADDRESS ENTRIES : $TotalEntries"
        if($BogusEntries){ Write-Host -f DarkYellow "+ BOGUS ENTRIES : $($Noise.Count)" }
        $TotalEntries += $($Noise.Count)
        Write-Host -f Red "+ TOTAL ENTRIES : $TotalEntries"

        if($StartRegEd){
            $TkExe = (Get-Command "taskkill.exe").Source
            &"$TkExe" -IM "regedit.exe"
            [string]$LastKeyPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit"
            [string]$LastKeyValue = "LastKey"
            $RegPath = $p.Replace('HKCU:\','Ordinateur\HKEY_CURRENT_USER\')
            Set-ItemProperty -Path "$LastKeyPath" -Name "$LastKeyValue" -Value "$RegPath"      
            $RegEditExe = (Get-Command "regedit.exe").Source
            &"$RegEditExe"        
        }
    }catch{
        Write-Error "$_"
    }

About Guillaume Plante
Guillaume Plante

A developper with a passion for technology, music, astronomy and art. Coding range: hardware/drivers, security, ai,. c/c++, powershell

Email : guillaumeplante.qc@gmail.com

Website : https://arsscriptum.ddns.net

Useful Links