如何在PowerShell中按名称和值过滤注册表项下的名称/值对?

问题描述 投票:4回答:3

我试图了解在PowerShell中使用的习语。

鉴于此脚本:

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

我得到了这个问题底部的输出。

我想获得属性的输出($key下的名称/值对),我可以在其中过滤名称和值。

例如,过滤列出所有具有以下内容的扩展:

  • xls*这样的名字
  • 或者像*\MSACCESS.EXE这样的价值

或排除过滤器:排除所有名称,如doc*

冷杉第一个过滤器,我想要一个像这样的结果:

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                                                                                                              

这是脚本的原始输出:

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                                                                                                              

编辑

我解决了部分问题:获取名称/值对列表。它使用PSCustomObject

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

(我应该如何包装该代码?)

任何有关过滤的帮助将非常感激

powershell registry powershell-v3.0
3个回答
4
投票

有一个更聪明的方法来枚举注册表值(找到它here)。它更像是PowerShell-way IMO。

我把它变成了一个单行:

(Get-ItemProperty $path).psobject.properties | 
   where {$_.name -like "xls*" -or $_.value -like "*\MSACCESS.EXE"} | 
      select name,value

更新:如@ mklement0的评论中所述,你应该注意PSPath中的属性PSParentPathPSChildNamePSDrivePSProviderpsobject.properties


6
投票

两部分答案。

我们从注册表中的$key开始:

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

由于$keyMicrosoft.Win32.RegistryKey,你无法直接获得名称值对。

第一步是用PSCustomObjects / Name对创建一个Value列表。 Name来自GetValueNames通过ForEach-Object管道。对于这些名称中的每一个,我们通过Value获得GetValue

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

第一步的替代方法是使用Select-Object使用-ExpandProperty,如Scott Saad所解释的:

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

第二步是通过$namevaluesName过滤Value

Where-Object有一些非常酷的Comparison运营商,accept regular expressions喜欢matchnotMatch等。

为了使代码更具可读性,你可以wrap lines(感谢Joey!)使用反引号(`)或利用PowerShell语法中的地方接受换行符,例如在管道(|)或左括号之后( {):

$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

0
投票

更强大的PSv4 +替代montonero's helpful answer:[1]

Get-Item $path -PipelineVariable key | ForEach-Object Property |
  ForEach-Object {
    $name = ($_, '')[$_ -eq '(default)'] # translate '(default)' to '' for API calls
    if (
         $name -like 'xls*' -or 
         ($value = $key.GetValue($name)) -like "*\MSACCESS.EXE"
       ) { [pscustomobject] @{ Name = $name; Value = $value } }
 }
  • -PipelineVariable key[Microsoft.Win32.RegistryKey]返回的Get-Item实例存储在变量$key中,供以后在管道中使用。
  • ForEach-Object Property枚举目标键的值名称(通过PowerShell添加到输出.Property实例的[Microsoft.Win32.RegistryKey] note属性)。
  • Where-Object脚本块中,$_然后引用手头的值名称,$key.GetValue(<valueName>)用于检索关联数据。 重要提示:在.Property数组中,PowerShell将默认值名称(即API级别的空字符串(''))转换为名称'(default)';因此,如果$_'(default)',你必须在调用''之前将其翻译为$_.GetValue(<valueName>),这是什么 ($_, '')[$_ -eq '(default)']
  • 然后[pscustomobject] @{ ... }构造并输出[pscustomobject]实例,其中.Name.Value属性反映了匹配值的名称和数据。

[1] montonero's answer简洁,在手头的情况下运作良好,但它带有警告:

PowerShell的注册表提供程序自动添加以下附加注释属性(NoteProperty类型的成员,反映在Get-Member的输出中),其中包含有关[pscustomobject]输出的Get-ItemProperty实例的目标注册表项的元数据:

  • PSPathPSParentPathPSChildNamePSDrivePSProvider

这些可能会以两种方式干扰基于.psobject.properties的过滤:

  • 对qazxsw poi使用通配符匹配可能会意外地包含这些属性。 例如,qazxsw poi将匹配$_.Name属性,即使它实际上不是注册表项的一部分。
  • 也许更假设,如果注册表项恰好具有与这些提供程序属性相同的值,则提供程序属性会影响(覆盖)这些值。 例如,如果密钥具有$_.Name -like '*drive*'值,则PSDrive将报告提供者属性值。
© www.soinside.com 2019 - 2024. All rights reserved.