Powershell、注册表和通配符,天哪

Powershell, registry and wildcards, oh my

鉴于...

HKLM\Software\   
  KeyName
    Property_1
    Property_2
    Property_[0-1] 
  Key*Name
    Property_1
    Property_2
    Property_[0-1]   
  Key@Name
    Property_1
    Property_2
    Property_[0-1]

我可以用

Get-Item -path:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name"

这将 return KeyNameKey*NameKey@Name,而

Get-Item -literalPath:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name"

将 return 只是 Key*Name。到目前为止,一切都很好。我可以根据需要使用 -path 或 -literalPath 来搜索是否使用通配符的键。但是属性带来了问题。

Get-ItemProperty -path:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\KeyName" -name:"Prop_[0-9]"

按预期工作,returns Prop_1 & Prop_2 来自 KeyName 键。并且

Get-ItemProperty -literalPath:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\KeyName" -name:"Prop_[0-9]"

按预期工作,return 只是 Prop_[0-9] 来自同一个键。但是,当您需要使用通配符在关键路径中包含通配符作为文字的路径中查找属性时,这一切都会失败。所以...

Get-ItemProperty -path:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name" -name:"Prop_[0-9]"

returns Prop_1 & Prop_2 来自所有三个键。根本不是期望的行为。

我曾希望能够使用 -`literalPath' 在 PSPath 上进行过滤,但这

Get-ItemProperty -literalPath:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name" -name:"Prop_[0-9]" | where {$_.PSPath -match [RegEx]::Escape("Key*Name")}

没有 return 正确的属性。 -literalPath 似乎也表示字面名称。所以我尝试像这样过滤 PSPathName

Get-ItemProperty -literalPath:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name" -name:"Prop_[0-9]" | where {(($_.PSPath -match [RegEx]::Escape("Key*Name")) -and ($_.Name -match "Prop_[0-9]"))}

但这行不通,因为一旦您真正获得了真正的属性,它们就不再是 .NET 类型,它们已经变成了 PSCustomObject。 这开始变得如此复杂,我想知道是否有更好的方法来进行。我应该注意,这里的最终目标是获取文字路径和文字 属性 名称列表,以便我可以移动、复制或删除属性。因此,给定路径 Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name 和名称 Prop_[0-9] 我最终会想要删除

HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name\Prop_1 

&

HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name\Prop_2

但不是

HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name\Prop_[0-9]

编辑:根据@Tomalak 的回答,我进行了一些简化,以简单地取回 属性 名称列表。看起来像这样

$keyPath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name"
$propExpr = "Prop_[0-9]"
((Get-Item -literalPath:$keyPath | Get-ItemProperty).PSObject.Properties | Where-Object Name -Match $propExpr | ForEach-Object {$_.Name})

这将通过文字路径获取注册表项并通过正则表达式匹配过滤其属性

$keyPath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name"
$propExpr = "Prop_[0-9]"

Get-Item -literalPath $keyPath -PipelineVariable key | Get-ItemProperty | ForEach-Object {
    $_.PSObject.Properties | Where-Object Name -Match $propExpr | ForEach-Object {
        [pscustomobject]@{
            key = $key.Name
            prop = $_.Name
            value = $_.Value
        }
    }
}

您当然可以 return 实际的 $key 而不是 $key.Name 如果这对您的任务更方便。