Reputation: 24463
When querying the registry value names like this:
Get-ItemProperty HKCU:\Software\Microsoft\Osk
You get a whole bunch of extra values.
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microsoft\Osk
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microsoft
PSChildName : Osk
PSDrive : HKCU
PSProvider : Microsoft.PowerShell.Core\Registry
WindowLeft : 100
WindowTop : 100
WindowWidth : 828
WindowHeight : 236
ClickSound : 1
Mode : 1
HoverPeriod : 1000
ScanInterval : 1000
UseDevice : 1
UseMouse : 0
UseKB : 1
ScanKey : 32
UseTextPrediction : 1
InsertSpace : 1
ShowNumPad : 0
What I want is only the value names (WindowLeft
, ...)
How can I do that?
Edit: string matches don't cut it. I do want legitimate registry value names to be included.
Example (could have done similar things with reg query hklm /v PS* /s
or reg query hkcu /v PS* /s
reg add "HKCU\Software\BeSharp.net\Test" /v "Foo" /t REG_SZ /d "Bar" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "Bar" /t REG_SZ /d "Foo" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "PSPath" /t REG_SZ /d "Foo" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "PSParentPath" /t REG_SZ /d "Foo" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "PSChildName" /t REG_SZ /d "Foo" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "PSDrive" /t REG_SZ /d "Foo" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "PSProvider" /t REG_SZ /d "Foo" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "1" /t REG_SZ /d "PSPath" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "2" /t REG_SZ /d "PSParentPath" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "3" /t REG_SZ /d "PSChildName" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "4" /t REG_SZ /d "PSDrive" /f
reg add "HKCU\Software\BeSharp.net\Test" /v "5" /t REG_SZ /d "PSProvider" /f
reg query "HKCU\Software\BeSharp.net\Test"
You can delete the above demo data with this:
reg delete "HKCU\Software\BeSharp.net\Test"
The reg query "HKCU\Software\BeSharp.net\Test"
returns this:
HKEY_CURRENT_USER\Software\BeSharp.net\Test
Foo REG_SZ Bar
Bar REG_SZ Foo
PSPath REG_SZ Foo
PSParentPath REG_SZ Foo
PSChildName REG_SZ Foo
PSDrive REG_SZ Foo
PSProvider REG_SZ Foo
1 REG_SZ PSPath
2 REG_SZ PSParentPath
3 REG_SZ PSChildName
4 REG_SZ PSDrive
5 REG_SZ PSProvider
But the PowerShell Get-ItemProperty "HKCU:\Software\BeSharp.net\Test"
returns this, overwriting the PS*
values in the registry:
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\BeSharp.net\Test
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\BeSharp.net
PSChildName : Test
PSDrive : HKCU
PSProvider : Microsoft.PowerShell.Core\Registry
Foo : Bar
Bar : Foo
1 : PSPath
2 : PSParentPath
3 : PSChildName
4 : PSDrive
5 : PSProvider
And adding a Select
clause skips all PS*
values, even if they came from the registry: PowerShell Get-ItemProperty "HKCU:\Software\BeSharp.net\Test" ^| Select * -Exclude PS*
:
Foo : Bar
Bar : Foo
1 : PSPath
2 : PSParentPath
3 : PSChildName
4 : PSDrive
5 : PSProvider
So: skip PS* values like PSPath
, PSParentPath
, PSChildName
, PSDrive
and PSProvider
(are there more?) when they are not in the registry, but include them when they are in the registry.
Bonus: Only list the names (not the values).
Upvotes: 5
Views: 4867
Reputation: 15470
Function Get-KeyProperty
to return registry values skipping PS*:
Function Get-KeyProperty {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[ValidateScript({Test-Path $_})]
[String]$RegPath
)
$Values = New-Object PSObject
Get-ItemProperty "$RegPath" |
Get-Member -MemberType NoteProperty |
Where-Object {$_.Name -notlike "PS*"} | Foreach {
$_ | Select-Object -ExpandProperty Name | Foreach {
$Value = Get-ItemProperty "$RegPath" -Name "$_"
$Values |
Add-Member -MemberType NoteProperty -Name "$_" -Value "$($Value."$_")"
}
}
Return $Values
}
And Get-HashedProperty
to get in Hashtable or JSON (Also excluding PS*):
Function Get-HashedProperty {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[ValidateScript({Test-Path $_})]
[String]$RegPath,
[Parameter(Mandatory=$False)]
[ValidateSet("Json","HashTable")]
[String]$As
)
$Hash = @{}
Get-ItemProperty "$RegPath" |
Get-Member -MemberType NoteProperty |
Where-Object {$_.Name -notlike "PS*"} | Foreach {
$_ | Select-Object -ExpandProperty Name | Foreach {
$Value = Get-ItemProperty "$RegPath" -Name "$_"
$Hash.Add("$_","$($Value."$_")")
}
}
If($As -eq "Json"){
$Hash = $Hash | ConvertTo-Json
}
Return $Hash
}
Upvotes: 0
Reputation: 802
I know this is truly old, but here's a function I added to my Profile to facilitate registry exploration:
Function Get-KeyProperty {
Param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[ValidateScript( {(Resolve-Path $_).Provider.Name -Like 'Registry'} )]
[String[]]
$Path,
[String[]]
$Name=@("*")
)
Process {
$Name.ForEach({ (Get-Item $Path).Property -like $_}).ForEach({
Begin {$Hash = @{}}
Process { $Hash += @{ $_ = (Get-Item $Path).GetValue($_)} }
End {[PSCustomObject]$Hash}
})
}}
PS C:\> set-alias gkp Get-KeyProperty
>>
>> $USF = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\'
>>
>> $TestPSNames = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\DummyWithPSNames\'
>>
PS C:\> gkp $TestPSNames
Hello PSPath
----- ------
World Not the real PS Path
PS C:\>>gkp $USF -Name p*,S*
Start Menu : C:\Users\keith\AppData\Roaming\Microsoft\Windows\Start Menu
SendTo : C:\Users\keith\AppData\Roaming\Microsoft\Windows\SendTo
Startup : C:\Users\keith\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
PrintHood : C:\Users\keith\AppData\Roaming\Microsoft\Windows\Printer Shortcuts
Personal : C:\Users\keith\Documents
Programs : C:\Users\keith\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
PS C:\>>$USF, $TestPSNames | gkp -Name S*,PS*,H* | fl
SendTo : C:\Users\keith\AppData\Roaming\Microsoft\Windows\SendTo
Startup : C:\Users\keith\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Start Menu : C:\Users\keith\AppData\Roaming\Microsoft\Windows\Start Menu
History : C:\Users\keith\AppData\Local\Microsoft\Windows\History
PSPath : Not the real PS Path
Hello : World
Upvotes: 2
Reputation: 2659
You can use the GetValueNames() method on the registry key objects:
$RegPath = "HKCU:\Software\Microsoft\Osk"
# Get just value names:
(Get-Item $RegPath).GetValueNames() -replace "^$", "(default)"
# Get PSObject excluding PS properties (this won't work when value names collide
# with reserved PS properties, e.g., PSPath, PSParentPath, PSChildName):
Get-Item $RegPath | ForEach-Object {
$_ | Get-ItemProperty | select ($_.GetValueNames() -replace "^$", "(default)")
}
# Get PSObject excluding PS properties (this works when the value names collide)
Get-Item $RegPath | ForEach-Object {
$RegKey = $_
$PropertyHash = @{}
$_.GetValueNames() -replace "^$", "(default)" | ForEach-Object {
$PropertyHash.$_ = $RegKey.GetValue($_)
}
New-Object PSObject -Property $PropertyHash
}
Upvotes: 5
Reputation: 36277
That's an easy one, you simple use Select, and tell it to Exclude PS*:
Get-ItemProperty HKCU:\Software\Microsoft\Osk|Select * -Exclude PS*
Edit: I should really read the whole question. Ok, to get just the names you can pipe to Get-Member -MemberType Properties, and then Select -Expand Name, and filter for items that start with PS
Get-ItemProperty HKCU:\Software\Microsoft\Osk|GM -MemberType Properties|Select -Expand Name| ?{!($_ -Match "^PS")}
Edit: Ok, if you want value names, and want to avoid PowerShell generated values, then we'll work around the built in providers and do a WMI query...
$HKEY_CLASSES_ROOT = 2147483648
$HKEY_CURRENT_USER = 2147483649
$HKEY_LOCAL_MACHINE = 2147483650
$HKEY_USERS = 2147483651
$HKEY_CURRENT_CONFIG = 2147483653
$reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$reg.EnumValues($HKEY_CURRENT_USER,"Software\Microsoft\Osk")|Select -Expand sNames
On a side note, I'm curious what 2147483652 is since it seems to skip that.
Edit: meaning 2147483652 found by searching for 2147483652 HKEY_CLASSES_ROOT 2147483648 HKEY_CURRENT_USER 2147483649 HKEY_LOCAL_MACHINE 2147483650 HKEY_USERS 2147483651 HKEY_CURRENT_CONFIG 2147483653 HKEY_DYN_DATA 2147483654
Many links answer it, including DLLBinder Example - Registry Access that indicates it is in winreg.h (which - not surprisingly - contains the HEX values).
So, for completeness:
$HKEY_CLASSES_ROOT = 2147483648 # 0x80000000
$HKEY_CURRENT_USER = 2147483649 # 0x80000001
$HKEY_LOCAL_MACHINE = 2147483650 # 0x80000002
$HKEY_USERS = 2147483651 # 0x80000003
$HKEY_PERFORMANCE_DATA = 2147483652 # 0x80000004
$HKEY_CURRENT_CONFIG = 2147483653 # 0x80000005
$HKEY_DYN_DATA = 2147483654 # 0x80000006
Upvotes: 5