我试图了解在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
(我应该如何包装该代码?)
任何有关过滤的帮助将非常感激
有一个更聪明的方法来枚举注册表值(找到它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
。
两部分答案。
我们从注册表中的$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
更强大的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
实例的目标注册表项的元数据:
PSPath
,PSParentPath
,PSChildName
,PSDrive
,PSProvider
这些可能会以两种方式干扰基于.psobject.properties
的过滤:
$_.Name
属性,即使它实际上不是注册表项的一部分。$_.Name -like '*drive*'
值,则PSDrive
将报告提供者属性值。