The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My work

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,822 other followers

how to filter name/value pairs under a registry key by name and value in PowerShell – Stack Overflow

Posted by jpluimers on 2017/09/06

A long time ago I asked this question how to filter name/value pairs under a registry key by name and value in PowerShell? – Stack Overflow [WayBack] but forgot to schedule a post about it.

It’s an interesting scenario, so lets start with a log of the outcome (it’s on my ix500 scanning VM which has Office15 a.k.a. Office 2013 installed) of this script:

$path = 'hkcu:\Software\Microsoft\Windows\CurrentVersion\Extensions'
$key = Get-Item $path
$key

$namevalues = $key | Select-Object -ExpandProperty Property | 
  ForEach-Object { 
    [PSCustomObject] @{ 
      Name = $_; 
      Value = $key.GetValue($_) 
    } 
  }
$namevalues | Format-Table

$matches = $namevalues | 
  Where-Object { 
    $_.Name -match '^xls' `
    -or $_.Value -match 'msaccess.exe$' 
  }
$matches | Format-Table

It outputs this:

Windows PowerShell
Copyright (C) 2014 Microsoft Corporation. All rights reserved.

PS C:\Users\ix500> $path = 'hkcu:\Software\Microsoft\Windows\CurrentVersion\Extensions'
PS C:\Users\ix500> $key = Get-Item $path
PS C:\Users\ix500> $key


    Hive: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion


Name                           Property
----                           --------
Extensions                     xlsx : C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE
                               xls  : C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE
                               mdb  : C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE
                               mda  : C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE
                               rtf  : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.rtf
                               dot  : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dot
                               dotm : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dotm
                               dotx : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dotx
                               docm : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.docm
                               docx : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.docx
                               doc  : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.doc


PS C:\Users\ix500> $namevalues = $key | Select-Object -ExpandProperty Property |
>>   ForEach-Object {
>>     [PSCustomObject] @{
>>       Name = $_;
>>       Value = $key.GetValue($_)
>>     }
>>   }
>> $namevalues | Format-Table
>>

Name                                                        Value
----                                                        -----
xlsx                                                        C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE
xls                                                         C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE
mdb                                                         C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE
mda                                                         C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE
rtf                                                         C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.rtf
dot                                                         C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dot
dotm                                                        C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dotm
dotx                                                        C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dotx
docm                                                        C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.docm
docx                                                        C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.docx
doc                                                         C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.doc


PS C:\Users\ix500> $matches = $namevalues |
>>   Where-Object {
>>     $_.Name -match '^xls' `
>>     -or $_.Value -match 'msaccess.exe$'
>>   }
>> $matches | Format-Table
>>

Name                                                        Value
----                                                        -----
xlsx                                                        C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE
xls                                                         C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE
mdb                                                         C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE
mda                                                         C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE


PS C:\Users\ix500>

The answer

A two part answer.

We start with the $key from the registry:

$path = 'hkcu:\Software\Microsoft\Windows\CurrentVersion\Extensions'
$key = Get-Item $path
$key
$key | Get-Member

Since $key is a Microsoft.Win32.RegistryKey, you cannot get the name value pairs out directly.

The first step is to create a list of PSCustomObjects with Name/Value pairs. The Name comes from the GetValueNames piped through a ForEach-Object. For each of those Names, we get the Value through GetValue:

$namevalues = $key.GetValueNames() | 
  ForEach-Object { 
    [PSCustomObject] @{ 
      Name = $_; 
      Value = $key.GetValue($_) 
    } 
  }
$namevalues | Format-Table

An alternative for the first step is to use the Select-Object using -ExpandProperty as explained byScott Saad:

$namevalues = $key | Select-Object -ExpandProperty Property | 
  ForEach-Object { 
    [PSCustomObject] @{ 
      Name = $_; 
      Value = $key.GetValue($_) 
    } 
  }
$namevalues | Format-Table

The second step is to filter the $namevalues either by Name or by Value.

The Where-Object has some pretty cool Comparison operators that accept regular expressions likematch, notMatch, etc.

To make the code more readable, you can wrap lines (thanks Joey!) either use the backtick (`) or take advantage of the places in the PowerShell syntax where it does accept line breaks, like after a pipe (|) or opening brace ({):

$matches = $namevalues | 
  Where-Object { 
    $_.Name -match '^xls' `
    -or $_.Value -match 'msaccess.exe$' 
  }
$matches | Format-Table

The result is as wanted:

Name    Value                                                                                         
----    -----                                                                                         
xlsx    C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE                                                       
xls     C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE                                                       
mdb     C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE                                                    
mda     C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE

The question

I’m trying to get a feel for the idioms to use in PowerShell.

Given this script:

$path = 'hkcu:\Software\Microsoft\Windows\CurrentVersion\Extensions'
$key = Get-Item $path
$key

I get the output at the bottom of this question.

I’d like to get output of the properties (the name/value pairs under the $key) where I can filter on both name and value.

For instance, filter to list all the Extensions that have:

  • name like xls*
  • or value like *\MSACCESS.EXE

Or an exclude filter: exclude all names like doc*

Fir the first filter, I’d want a result like this:

Name                           Value                                                                                                                                                       
----                           --------                                                                                                                                                       
xlsx                           C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE                                                                                                                 
xls                            C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE                                                                                                                 
mdb                            C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE                                                                                                              
mda                            C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE                                                                                                              

This is the original output of the script:

Hive: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion
Name                           Property                                                                                                                                                       
----                           --------                                                                                                                                                       
Extensions                     rtf  : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.rtf                                                                                                         
                               dot  : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dot                                                                                                         
                               dotm : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dotm                                                                                                        
                               dotx : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.dotx                                                                                                        
                               docm : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.docm                                                                                                        
                               docx : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.docx                                                                                                        
                               doc  : C:\PROGRA~2\MICROS~1\Office15\WINWORD.EXE ^.doc                                                                                                         
                               xlsx : C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE                                                                                                                 
                               xls  : C:\PROGRA~2\MICROS~1\Office15\EXCEL.EXE                                                                                                                 
                               mdb  : C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE                                                                                                              
                               mda  : C:\PROGRA~2\MICROS~1\Office15\MSACCESS.EXE                                                                                                              

Edit

I solved part of the problem: getting a list of Name/Value pairs. It uses PSCustomObject:

$namevalues = $key.GetValueNames() | ForEach-Object { [pscustomobject]@{ Name=$_; Value=$key.GetValue($_) } }
$namevalues

(How should I wrap that code?)

Any help with the filtering would be much appreciated

–jeroen

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: