6

我正在尝试了解在 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

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

任何有关过滤的帮助将不胜感激

4

3 回答 3

6

一个两部分的答案。

我们$key从注册表开始:

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

由于$keyMicrosoft.Win32.RegistryKey,因此您无法直接获取名称值对。

第一步是使用/对创建PSCustomObjects列表。来自通过ForEach-Object管道传输的GetValueNames。对于每个名称,我们通过GetValue获得:NameValueNameValue

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

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

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

第二步是过滤$namevaluesbyName或 by Value

Where-Object有一些非常酷的比较运算符,它们接受正则表达式,如match,notMatch等。

为了使代码更具可读性,您可以换行(感谢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
于 2013-07-25T07:22:25.623 回答
5

枚举注册表值有一种更聪明的方法(在此处找到)。它更像是 IMO 的 powershell 方式。

我把它变成了一个单行:

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

更新:正如@mklement0 评论中所指出的,您应该注意属性PSPathPSParentPathPSChildNamePSDrivePSProvider.psobject.properties

于 2017-09-04T11:49:47.343 回答
2

一个更强大的 PSv4+ 替代montonero的有用答案[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存储in 变量[Microsoft.Win32.RegistryKey]返回的实例,以供以后在管道中使用。Get-Item$key

  • ForEach-Object Property枚举目标键的值名称(通过.PropertyPowerShell 添加到输出[Microsoft.Win32.RegistryKey]实例的 note 属性)。

  • Where-Object脚本块内部,$_然后引用手头的值名称,并$key.GetValue(<valueName>)用于检索关联的数据。

    • 重要提示:在.Property数组中,PowerShell 将默认值 name,即API 级别的空字符串( ) 转换为 name ;因此, if is ,您必须在调用之前将其翻译为,这就是这样做的。'''(default)'$_'(default)'''$_.GetValue(<valueName>)
      ($_, '')[$_ -eq '(default)']
  • [pscustomobject] @{ ... }然后构造并输出一个[pscustomobject]实例,其.Name.Value属性反映匹配值的名称和数据。


[1] montonero 的回答简洁明了,在手头的情况下效果很好,但有一些警告:

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

  • PSPath, PSParentPath, PSChildName, PSDrive,PSProvider

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

  • 使用通配符匹配$_.Name可能会意外包含这些属性。

    • 例如,$_.Name -like '*drive*'将匹配该PSDrive属性,即使它实际上不是注册表项的一部分。
  • 也许更假设的是,如果注册表项恰好具有与这些提供程序属性同名的值,则提供程序属性会隐藏(覆盖)这些值。

    • 例如,如果键有PSPath值,$_.Value将改为报告提供者属性值。
于 2019-04-23T19:01:29.350 回答