Given...
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]
I can use
Get-Item -path:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name"
which will return KeyName
, Key*Name
and Key@Name
, while
Get-Item -literalPath:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name"
will return just Key*Name
. So far, so good. I can use -path or -literalPath as needed to either search for a key with wildcards or not. But properties pose a problem.
Get-ItemProperty -path:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\KeyName" -name:"Prop_[0-9]"
works as expected and returns Prop_1
& Prop_2
from the KeyName
key. And
Get-ItemProperty -literalPath:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\KeyName" -name:"Prop_[0-9]"
works as expected and returns just Prop_[0-9]
from the same key. But it all fails apart when you need to use a wildcard to find properties, in a path that includes a wildcard character as a literal in the key path. So...
Get-ItemProperty -path:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name" -name:"Prop_[0-9]"
returns Prop_1
& Prop_2
from all three keys. Not the desired behavior at all.
I had hoped to be able to filter on PSPath
using -`literalPath' but this
Get-ItemProperty -literalPath:"Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name" -name:"Prop_[0-9]" | where {$_.PSPath -match [RegEx]::Escape("Key*Name")}
does not return the correct properties. It seems that a -literalPath
means a literal name also. So I tried filtering on PSPath
and Name
like so
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]"))}
But that doesn't work because once you actually get real properties, they are no longer a .NET type, they have been shat into a PSCustomObject
.
And that is starting to get so complicated I wonder if there is a better way to proceed. I should note that the ultimate goal here is to get both a literal path and a list of literal property names, so that I can move, copy or delete the properties. So, given a path of Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name
and a name of Prop_[0-9]
I will eventually want to, for example, delete
HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name\Prop_1
&
HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name\Prop_2
but not
HKEY_LOCAL_MACHINE\SOFTWARE\Key*Name\Prop_[0-9]
EDIT: Based on the answer from @Tomalak I have simplified a bit, to simply get back a list of property names. That looks like this
$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})
CodePudding user response:
This will get a registry key by literal path and filter its properties by regex match
$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
}
}
}
Instead of the $key.Name
you can of course return the actual $key
if that's more convenient for your task.