header1   header
header
header Register : : Login header
header
connector   connector
menuleft menuright
submenu   submenu
left
Recursive Registry Search with Microsoft.Win32.RegistryKey
Last Post 07 May 2009 02:34 AM by nickilla. 3 Replies.
Printer Friendly
  •  
  •  
  •  
  •  
  •  
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Author Messages Not Resolved
anti121User is Offline
New Member
New Member
Posts:14
Avatar

--
01 Jan 2009 09:43 AM
    What I am trying to do is write the quickest recursive registry search in PowerShell that is possible. Depending on how big the hive is and how fast the machine is affects the completion time, but what I have noticed is that using the built-in search in regedit.exe is much faster than my script below. Are there any ways that I can make the script below faster?

    Eventually it will be made to accept a replace parameter to be able to replace search matches with a new value.

    • Is Windows.Win32.RegistryKey the fastest API to use?
    • Are there any bottle necks with the current implementation?

    <!--
    
    Code highlighting produced by Actipro SyntaxEditor
    http://www.ActiproSoftware.com/Products/DotNet/
    
    -->
    function RecReg {
        param (
            [Microsoft.Win32.RegistryKey]$HiveRoot = `
            $(throw "A hive root of type Microsoft.Win32.RegistryKey is required."),
            [string]$SubKeyPath = "\", 
            [string]$Find = $(throw "A search string is required.")
        )
        trap [System.Security.SecurityException]{
            Write-Host ("Error invoking: " + $_.InvocationInfo.InvocationName + `
                " for " + $HiveRoot.Name + "\" + $SubKeyPath + `
                " on line " + $_.InvocationInfo.ScriptLineNumber + `
                " the error was: " +  $_.Exception.Message)
            continue
    
        }
        if ($HiveRoot.OpenSubKey($SubKeyPath).ValueCount) {
            foreach ($vName in $HiveRoot.OpenSubKey($SubKeyPath).GetValueNames()) {
                [string]$vData = $HiveRoot.OpenSubKey($SubKeyPath).GetValue($vName)
                if ($vData -eq $Find) {
                    write-host $HiveRoot.OpenSubKey($SubKeyPath).Name `
                        -BackgroundColor white -ForegroundColor black
                    write-host $vName -ForegroundColor yellow
                    write-host $vData -ForegroundColor darkgreen
                }
            }
        }
        if ($HiveRoot.OpenSubKey($SubKeyPath).SubKeyCount) {
            foreach ($kName in $HiveRoot.OpenSubKey($SubKeyPath).GetSubKeyNames()) {
                $Path = ($SubKeyPath + "\" + $kName).Replace("\\","")
                RecReg -HiveRoot $HiveRoot -SubKeyPath $Path -Find $Find
    
            }
        }
    }
    
    $Hive = [Microsoft.Win32.Registry]::LocalMachine
    
    Measure-Command {RecReg -HiveRoot $Hive -SubKeyPath "\" -Find $env:COMPUTERNAME}
    
    anti121User is Offline
    New Member
    New Member
    Posts:14
    Avatar

    --
    01 Jan 2009 09:16 PM
    Below the function has been modified to collect statistics about how many registry keys, values and matches have been iterated as well as some metrics from test systems.

    Here are the metrics from a VM running on ESX server (fairly fast) with a ton of software installed:
    Days              : 0
    Hours             : 0
    Minutes           : 6
    Seconds           : 42
    Milliseconds      : 45
    Ticks             : 4020456784
    TotalDays         : 0.00465330646296296
    TotalHours        : 0.111679355111111
    TotalMinutes      : 6.70076130666667
    TotalSeconds      : 402.0456784
    TotalMilliseconds : 402045.6784

    Finished processing: 309205 registry keys, 380901 registry values, 25 matches were found.


    Here is the modified script that collects and displays statistics:

    Any ideas to make this faster?

    function RecReg {
    param (
    [
    Microsoft.Win32.RegistryKey]$HiveRoot = `
    $(
    throw "A hive root of type Microsoft.Win32.RegistryKey is required."),
    [
    string]$SubKeyPath = "\",
    [
    string]$Find = $(throw "A search string is required."),
    [
    ref]$Counter
    )
    $Counter.value.kCount += 1
    trap [System.Security.SecurityException]{
    Write-Host ("Error invoking: " + $_.InvocationInfo.InvocationName + `
    " for " + $HiveRoot.Name + "\" + $SubKeyPath + `
    " on line " + $_.InvocationInfo.ScriptLineNumber + `
    " the error was: " + $_.Exception.Message)
    continue
    }
    if ($HiveRoot.OpenSubKey($SubKeyPath).ValueCount) {
    foreach ($vName in $HiveRoot.OpenSubKey($SubKeyPath).GetValueNames()) {
    [
    string]$vData = $HiveRoot.OpenSubKey($SubKeyPath).GetValue($vName)
    if ($vData -eq $Find) {
    write-host $HiveRoot.OpenSubKey($SubKeyPath).Name `
    -BackgroundColor white -ForegroundColor black
    write-host $vName -ForegroundColor yellow
    write-host $vData -ForegroundColor darkgreen
    $Counter.value.mCount += 1
    }
    $Counter.value.vCount += 1
    }
    }
    if ($HiveRoot.OpenSubKey($SubKeyPath).SubKeyCount) {
    foreach ($kName in $HiveRoot.OpenSubKey($SubKeyPath).GetSubKeyNames()) {
    $Path = ($SubKeyPath + "\" + $kName).Replace("\\","")
    RecReg `
    -HiveRoot
    $HiveRoot `
    -SubKeyPath
    $Path `
    -Find
    $Find `
    -Counter
    $Counter
    }
    }
    }

    $Counter = @{}
    $Counter.kCount = 0
    $Counter.vCount = 0
    $Counter.mCount = 0

    $Hive = [Microsoft.Win32.Registry]::LocalMachine

    Measure-Command {
    RecReg `
    -HiveRoot
    $Hive `
    -SubKeyPath
    "\" `
    -Find
    $env:COMPUTERNAME `
    -Counter ([
    ref]$Counter)
    }

    Write-Host ("Finished processing: " + `
    $Counter.kCount + " registry keys, " + `
    $Counter.vCount + " registry values, " + `
    $Counter.mCount + " matches were found."
    )
    anti121User is Offline
    New Member
    New Member
    Posts:14
    Avatar

    --
    01 Jan 2009 10:09 PM
    For comparison, a colleague wrote a perl script that processes the same number of registry keys and values (ran it on the same VM) in 42 seconds. The perl script uses the Win32API::Registry module to process the registry.

    Is PowerShell just really slow or is there something wrong with my script?

    If anyone wants to take a look at the perl script let me know.
    nickillaUser is Offline
    New Member
    New Member
    Posts:1
    Avatar

    --
    07 May 2009 02:34 AM
    Hello anti121,

    have you found the solution meanwhile?
    I am also looking for a fast way right now.

    tia,
    Marco
    You are not authorized to post a reply.


    Active Forums 4.3
    right
    footer   footer
    footer Sponsored by Quest Software • SAPIEN Technologies • Compellent • Microsoft Windows Server 2008 R2 footer
    footer   footer