How to check the existence of registry key in HKEY_CURRENT_CONFIG - powershell

How to check the presence of registry key named "Mon12345678" under HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\VIDEO\ {CD73268F-4662-42EC-80F6-182E03DE7017}\0000 regsitry hive? We can validate till HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\VIDEO directly and then run random check under "Video" until we get the sub registry key called "Mon12345678"?
I tried the below code snippet
Test-Path -Path "HKCC:\System\CurrentControlSet\Control\VIDEO\ *\Mon12345678" -ErrorAction SilentlyContinue
But the result shows false even though the sub registry hive is found. How to tackle the problem?

The HKEY_CURRENT_CONFIG registry hive is not predefined as a PowerShell drive name HKCC:, so unless you defined such a drive yourself with New-PSDrive, it won't exist.
(Get-PSDrive -psProvider Registry).Name shows you which registry-based drives are defined; by default, it is only HKLM: (HKEY_LOCAL_MACHINE) and HKCU: (HKEY_CURRENT_CONFIG).
Short of defining your own HKCC: drive, you can prefix a registry hive name with registry:: (the provider name) in order to target a hive; e.g.:
# Test the existence of a key known to exist in the HKEY_CURRENT_CONFIG registry hive,
# using provider prefix 'registry::'
PS> Test-Path -Path 'registry::HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control'
True
Therefore, to test the existence of a subkey named Mon12345678 across all subkeys (*) of key HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\VIDEO, use the following:
$keyPath = 'registry::HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\VIDEO'
Test-Path -Path "$keyPath\*\Mon12345678"
If, by contrast, you want to test the existence of a value (a property of a registry key) named Mon12345678, you cannot use a single Test-Path call, because Test-Path can only operate on key paths, not paths ending in value names.
See this answer for background information.
$keyPath = 'registry::HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\VIDEO'
[bool] (Get-ItemProperty -EA ignore "$keyPath\*" 'Mon12345678')

Did you try?
To search part of the registry, use the following syntax:
REG Query HKxx\subkey [/D|/K|/V] /F "search_pattern" /S [/E] [/C]
To search an entire registry hive, just omit the subkey:
REG Query HKxx [/D|/K|/V] /F "search_pattern" /S [/E] [/C]
Source of the solution and full post can be found here

Related

How to refer to HKEY_CLASSES_ROOT in PowerShell?

New-Item -Path "HKCR:\Directory\Background\shell\customname" -Force
I've been doing the same thing for HKCU and KHLM but when I try HKCR I get errors in PowerShell. how am I supposed to do it for HKEY_CLASSES_ROOT?
I searched for a solution but couldn't find any.
Okay I figured out on my own,
checked Get-PSDrive
and saw the only registry aliases available by default on Windows/PowerShell are
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
so, what I did, following this, was to add a new alias for HKEY_CLASSES_ROOT that is called HKCR
New-PSDrive -Name "HKCR" -PSProvider Registry -Root "HKEY_CLASSES_ROOT"
Defining a custom drive whose root is HKEY_CLASSES_ROOT, as shown in your own answer, is definitely an option, especially for repeated use.
Ad hoc, you can alternatively use the Registry:: provider prefix directly with native registry paths:
New-Item -Path 'Registry::HKEY_CLASSES_ROOT\Directory\Background\shell\customname' -Force
Note:
The Registry part of the prefix is the provider name, as shown in Get-PSProvider's output.
Hypothetically, multiple providers with the same name could be registered, in which case you can prefix the name with the implementing module name for disambiguation; in the case of the registry provider, this module-qualified prefix is Microsoft.PowerShell.Core\Registry::[1] However, it's fair to assume that no third-party providers will choose a name that conflicts with the providers that ship with PowerShell, so Registry:: (or registry::, case doesn't matter), should do.
Note that the module-qualified provider name does show up in the prefix of the .PSPath property that provider items, such as reported by Get-Item and Get-ChildItem, are decorated with, e.g.:
PS> (Get-Item HKCU:\Console).PSPath
Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Console
[1] Note that the Core part of the name does not refer to the PowerShell (Core) edition; it simply denotes a module that is at the core of either edition.

Powershell gets stuck creating a registry key

I tried to create a new registry key using powershell
PS HKCU:\> New-Item -Path .\Software\Google\Chrome\NativeMessagingHosts\ -Name TEST -Value TEST
But somehow the process doesn't return I have to manually exit with CTRL+C
When I browse the key with regedit I see it was created, but why does the console not finish the command ?
Did anyone ever have a similar problem?
As commented, Your code does not work because you need to either provide a proper registry path like
HKCU:\Software\Google\Chrome\NativeMessagingHosts
OR use Set-Location HKCU: first, so the New-Item cmdlet will know where to create something new.
A registry Key does not have a value, only registry entries (properties) do.
So in order to create a new key with name "TEST", and create a new entry in that new key, use two lines of code:
New-Item -Path 'HKCU:\Software\Google\Chrome\NativeMessagingHosts' -Name 'TEST'
New-ItemProperty -Path 'HKCU:\Software\Google\Chrome\NativeMessagingHosts\TEST' -Name 'Test' -Value 'Just Testing'
You can also do this in one single statement using .NET SetValue()
Sets the name/value pair on the specified registry key, using the specified registry data type. If the specified key does not exist, it is created.
[Microsoft.Win32.Registry]::SetValue("HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\TEST", "Test", "Just Testing", 1)
The last parameter (in this case 1) is the RegistryValueKind you want to set. (in this example a String)

How to retrieve original, unresolved (unexpanded) registry value?

In the System Properties > Environment Variables > User variables > PATH contains:
%USERPROFILE%\Downloads\SysinternalsSuite;%USERPROFILE%\bin
The value can be retrieved with:
PS C:\src\t> (Get-ItemProperty -Path HKCU:\Environment).PATH
C:\Users\lit\Downloads\SysinternalsSuite;C:\Users\lit\bin
Is there any way to get the original value without variable expansion? It almost seems like Get-ItemProperty needs a -Raw switch.
PetSerAl, as many times before, has provided an effective solution in a terse comment on the question.
Indeed, PowerShell's Get-ItemProperty / Get-ItemPropertyValue cmdlets currently (PowerShell 7.3.0) lack the ability to retrieve a REG_EXPAND_SZ registry value's raw value, meaning the value as stored in the registry before the embedded environment-variable references (e.g., %USERPROFILE%) are expanded (interpolated).
Direct use of the .NET API is therefore needed:
(Get-Item -Path HKCU:\Environment).GetValue(
'PATH', # the registry-value name
$null, # the default value to return if no such value exists.
'DoNotExpandEnvironmentNames' # the option that suppresses expansion
)
See [Microsoft.Win32.RegistryKey].GetValue().
Note: 'DoNotExpandEnvironmentNames' is automatically converted to [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentVariables by PowerShell; you may use the latter as well.

Differentiate Registry Key from Value paths

Is there an equivalent of [System.IO.DirectoryInfo] and [System.IO.FileInfo] for differentiating Registry Keys from Values? I want to evaluate a path and log for the user what the final target of the path is.
So far, this is what I have, and it's kinda ugly.
$path = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\SomeJunkHereToTestFailure'
try {
if ((Get-Item -path:$path -errorAction:stop).GetType().name -eq 'RegistryKey') {
'Registry Key'
}
} catch {
try {
if ((Get-ItemProperty -path:(Split-Path $path -parent) -name:(Split-Path $path -leaf) -errorAction:stop).GetType().name -eq 'PSCustomObject') {
'Registry Value'
}
} catch {
'What is this?'
}
}
Hoping for something more elegant and also consistently correct.
Ok, so after digging around for awhile, canonically speaking, this:
HKEY_LOCAL_MACHINE\SOFTWARE\Path\To\Something
Is always a path to a key.
Look at reg.exe query. Look at how Get-ItemProperty works. Notice in regedit.exe that you can copy key names, but not a "path" to a specific value. Look at how .reg files are written. Look at Registry.GetValue() and Registry.SetValue(). Or Registry.LocalMachine.OpenSubKey().GetValue(). Microsoft clearly thinks that registry paths always point to keys.
If you have software that's using HKEY_LOCAL_MACHINE\SOFTWARE\Path\To\A\Value to refer to a value in the registry, then they're not using standard registry paths that Windows understands.
That's why you run these the way you do:
reg.exe query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v "ProductName"
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name "ProductName"
[Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SOFTWARE\Microsoft\Windows NT\CurrentVersion').GetValue('ProductName')
[Microsoft.Win32.Registry]::GetValue('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion','ProductName', $false)
That last one is nice because it doesn't error. If it can't find the value, it returns the third argument. It does, however, require the long hive name at the start as far as I can tell.
So, Test-Path -Container can tell you if it's a key. Microsoft.Win32.Registry.GetValue() can tell you if it's a value... with some manipulation.
Original answer (THIS DOES NOT WORK):
Use Test-Path:
$path = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\SomeJunkHereToTestFailure'
# Is it a Key?
Test-Path -Path $path -PathType Container
# Is it a Value?
Test-Path -Path $path -PathType Leaf
As for...
Is there an equivalent of [System.IO.DirectoryInfo] and [System.IO.FileInfo]
Not that I've ever seen or heard of to date.
However, take a look at the below to see if they can fit your need or you may be ableto tweak them to accomplish your goals.
Powershell Registry Cmdlets utilizing the .Net StdRegProv
This Script is a collection of PowerShell cmdlets that can be run in either x86 or x64 processes to handle common registry operations utilizing alternate registry views. This script is compatible with PowerShell versions 2.0 or later.
Download RegistryCmdlets.ps1
https://gallery.technet.microsoft.com/Powershell-Registry-19689888
Or of course is back to writing your own as you are posting here:
See also as you look at your effor to cultivate your own:
Registry Cmdlets: First Steps with CDXML
In this post, I’ll show you how to get started with CDXML. Before that, though, I’d better explain CDXML...
Cmdlet definition XML (CDXML) is a way to create a Windows PowerShell module from a WMI class by using the cmdlets-over-objects technology that was introduced in Windows PowerShell 3.0. As usual, it’s always easier to show you an example:
https://blogs.technet.microsoft.com/heyscriptingguy/2015/02/03/registry-cmdlets-first-steps-with-cdxml/
Registry Cmdlets: Working with the Registry
The bad news is that there aren’t any cmdlets for working with the registry. There’s a Registry provider, which means you can use the Item and ItemProperty cmdlets to manage the local registry—but there aren’t any specific registry cmdlets associated with the provider.
The good news is that we can adopt the approach that many teams at Microsoft have taken and create our own by using cmdlet definition XML (CDXML). A Common Information Model (CIM) class is wrapped in some fairly simple XML and published as a Windows PowerShell module. If you look in the Modules folder on a computer running Windows 8.1, Windows 8, Windows Server 2012 R2, or Windows Server 2012, you will find many files with a CDXML extension:
https://blogs.technet.microsoft.com/heyscriptingguy/2015/02/02/registry-cmdlets-working-with-the-registry
There's a problem with the premise of your question: Ending a registry path - composed of key names - with a value name is not supported - at least neither with the .NET Framework registry types nor with reg.exe nor with PowerShell's registry drive provider.
For instance, to refer to value WindowSize of registry key
HKEY_CURRENT_USER\Control Panel\Colors, you CANNOT use the following path:
# NOT a valid path, because 'WindowSize' is a *value*, not a *key*.
HKEY_CURRENT_USER\Control Panel\Colors\WindowSize
Even if you yourself decide to support such paths in your functions (and there may be utilities that similarly accept that), note that they are ambiguous, because a given registry key can have both a value and a subkey with a given name.
With that limitation in mind, your own code from your question is probably the best you can do (though it can be streamlined a little).
Is there an equivalent of [System.IO.DirectoryInfo] and [System.IO.FileInfo] for differentiating Registry Keys from Values?
The equivalent of [System.IO.DirectoryInfo] (filesystem directory) is [Microsoft.Win32.RegistryKey] (registry key).
By contrast, [System.IO.FileInfo] (filesystem file) has NO counterpart for registry values:
Registry values are represented as properties of registry items (keys) in the PS registry drive provider rather than items in their own right, and such properties are (awkwardly) represented as non-specific [System.Management.Automation.PSCustomObject] instances.
Similarly, registry values have no type representation in the .NET Framework (you only request their data by name).
Fundamentally, in terms of object models, registry values do not correspond to filesystem files; read on for more.
Optional reading: how the registry object model maps onto PowerShell drive-provider concepts in contrast with the filesystem object model
It comes down to this: in the filesystem, a directory's files are child items, whereas in the registry, a key's values are properties of that key.
Only container-type children are represented as child items in both providers (sub-directories in the case of the filesystem provider, sub-keys in case of the registry provider).
In the context of the FileSystem provider, files and directories are both (sub-types of) items.
Files are represented as [System.IO.FileInfo] instances, and directories as [System.IO.DirectoryInfo].
A leaf item is invariably of subtype file, whereas a container (interior) item is invariably of subtype directory (folder).
Therefore, you can use Test-Path -PathType Leaf to test for a file and Test-Path -PathType Container to test for a directory.
In the context of the Registry provider, it is only keys that are items.
Keys are represented as [Microsoft.Win32.RegistryKey] instances.
Since all keys are (potentially) containers, the registry provider has no concept of a leaf item.
Therefore, use of Test-Path -PathType <type> with a registry path is pointless,
because with -PathType Leaf the result is always $False, and with -PathType Container it is always $True.
By contrast, registry values are represented as properties (the equivalent of what the last-modified date is to a filesystem item, for instance).
Use the *-ItemProperty* cmdlets to read and write registry values.

How can I programmatically find a users HKEY_USERS registry key using powershell?

I wonder if there is a way to find a local user's registry key in HKEY_USERS if you know the login-name of that user on the local machine. I want to programmatically add stuff to a specific user's registry keys (Autorun for example), but I only know the username. How can I determine which of the cryptic users in HKEY_USERS actually belongs to a specific username?
$User = New-Object System.Security.Principal.NTAccount($env:UserName)
$sid = $User.Translate([System.Security.Principal.SecurityIdentifier]).value
The above snippet gives you the SID of the logged-in user. This when appended to the HKEY_USERS givs you the right path for that username.
New-PSDrive HKU Registry HKEY_USERS
Get-Item "HKU:\${sid}"
This answer is not complete, as HKEY_USERS does not contain all the users, just those that are currently active.
You'll need to load the registry hive for the user(s) you want to work with using
reg load hku\ThatUserName C:\Users\ThatUserName\NTUSER.DAT
See this SO answer for an example of how to load the registry hive for all the user(s).
You can then access the registry for that user with
Set-Location HKU:\ThatUserName
Or call New-PSDrive to give the user's registry it's own drive, like so:
New-PSDrive -Name HKThatUser -PSProvider Registry -Root HKU\ThatUserName
Set-Location HKThatUser:
Be sure to unload the registry, and do garbage collection to ensure the hive is released when done:
reg unload hku\ThatUserName
[gc]::collect()
See this post for more info
This does it for me
ls 'hklm:software/microsoft/windows nt/currentversion/profilelist' | ? {
$_.getvalue('profileimagepath') -match 'Steven'
} | % pschildname
Example