我试图了解在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
(我应该如何包装该代码?)
非常感谢任何有关过滤的帮助
答案 0 :(得分:5)
两部分答案。
我们从注册表中的$key
开始:
$path = 'hkcu:\Software\Microsoft\Windows\CurrentVersion\Extensions'
$key = Get-Item $path
$key
$key | Get-Member
由于$key
是Microsoft.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
第二步是按$namevalues
或Name
过滤Value
。
Where-Object有一些非常酷的Comparison运营商,accept regular expressions喜欢match
,notMatch
等。
为了使代码更具可读性,您可以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
答案 1 :(得分:4)
有一种更聪明的方法可以枚举注册表值(找到它here)。而且它更像是PowerShell-way IMO。
我把它变成了一个单行:
(Get-ItemProperty $path).psobject.properties |
where {$_.name -like "xls*" -or $_.value -like "*\MSACCESS.EXE"} |
select name,value
更新:正如@ mklement0的评论中所述,您应该注意属性PSPath
,PSParentPath
,PSChildName
,PSDrive
,和PSProvider
中的psobject.properties
。
答案 2 :(得分:0)
montonero's helpful answer的更强大的PSv4 +替代方案: [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转换默认值名称,它是空字符串({{ 1}})在API级别上,命名为''
;因此,如果'(default)'
是$_
,则必须在调用'(default)'
之前将其转换为''
,这是$_.GetValue(<valueName>)
的作用。 ($_, '')[$_ -eq '(default)']
然后构造并输出一个[pscustomobject] @{ ... }
实例,该实例具有[pscustomobject]
和.Name
属性,它们反映匹配值的名称和数据。
[1] montonero's answer简洁明了,适用于当前情况,但有一些警告:
PowerShell的注册表提供程序自动添加以下包含元数据(类型为.Value
的成员,反映在NoteProperty
的输出中) >关于Get-Member
输出的[pscustomobject]
实例的目标注册表项 :
Get-ItemProperty
,PSPath
,PSParentPath
,PSChildName
,PSDrive
这些可以通过两种方式干扰基于PSProvider
的过滤:
再次使用通配符匹配.psobject.properties
可能会意外地包含这些属性。
$_.Name
会与$_.Name -like '*drive*'
属性匹配,即使它实际上不是注册表项的一部分。也许更假设,如果注册表项恰好具有与这些提供程序属性相同的名称,则提供程序属性 shadow (覆盖)这些值。
PSDrive
,则PSPath
将报告 provider 属性值。