I've been doing some work lately involving the registry and Windows PowerShell. One of the tasks was to create new registry keys and entries. But because I wanted to some robustness, I wanted a way to verify if a given key or entry already existed.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Using Get-ItemProperty is the easy way to accomplish this.
[cc lang="PowerShell"]
PS S:\> get-itemproperty -Path HKCU:\jdhit\powershell -name test
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\jdhit\powershell
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\jdhit
PSChildName : powershell
PSDrive : HKCU
PSProvider : Microsoft.PowerShell.Core\Registry
Test : Foo
[/cc]
This is just fine if it exists, but a pain if it doesn't.
[cc lang="PowerShell"]
PS S:\> get-itemproperty -Path HKCU:\jdhit\powershell -name bogus
Get-ItemProperty : Property bogus does not exist at path HKEY_CURRENT_USER\jdhit\powershell.
At line:1 char:17
+ get-itemproperty <<<< -Path HKCU:\jdhit\powershell -name bogus
+ CategoryInfo : InvalidArgument: (bogus:String) [Get-ItemProperty], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemPr
opertyCommand
[/cc]
So I ended up writing a wrapper function that returns True or False if the item exist. The function handles the error handling and also takes transactions into account, since that might be a factor when working with the registry.
[cc lang="PowerShell"]
Function Test-RegistryItem {
<#
.SYNOPSIS
Test the the existence of a registry value
.DESCRIPTION
This command will determine if a given registry key exists. You must specify a registry path
and the name of the key.
.PARAMETER Path
The registry path using the registry PSDrive format, ie HLKLM:
.PARAMETER Property
The property name to check. The parameter as an alias of Name.
.PARAMETER UseTransaction
Use an active transaction. This parameter is valid only when a transaction is in progress.
For more information, see about_Transactions.
.EXAMPLE
PS C:\> test-itemproperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" -Property "Shell"
True
.INPUTS
[String]
.OUTPUTS
[Boolean]
.NOTES
NAME: Test-RegistryItem
AUTHOR: Jeffery Hicks
VERSION: 1.0
LASTEDIT: 10/01/2010
Learn more with a copy of Windows PowerShell 2.0: TFM (SAPIEN Press 2010)
.LINK
Get-ItemProperty
.LINK
https://jdhitsolutions.com/blog
#>
[cmdletbinding()]
Param (
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a registry path using the PSDrive format.")]
[ValidateNotNullOrEmpty()]
[string]$Path,
[Parameter(Position=1,Mandatory=$True,HelpMessage="Enter a registry key name.")]
[ValidateNotNullOrEmpty()]
[Alias("name")]
[string]$Property,
[Switch]$UseTransaction
)
Write-Verbose ("Looking for {0} in {1}" -f $Property,$Path)
if (Test-Path $path)
{
if ($UseTransaction)
{
$item=Get-ItemProperty -Path $path -Name $property -ErrorAction "SilentlyContinue" -UseTransaction
} else
{
$item=Get-ItemProperty -Path $path -Name $property -ErrorAction "SilentlyContinue"
}
if ($item )
{
#display the item if using -Verbose
Write-Verbose ($item | select * | Out-String)
$True
}
else
{
Write-Verbose "Not found"
$False
}
}
else
{
Write-Warning "Failed to find $path"
$False
}
} #end function
[/cc]
The function uses the same parameters as Get-ItemProperty, although it adds an extra step to verify that the registry path exists by using Test-Path. Now, I can easily test for a key.
[cc lang="PowerShell"]
PS S:\> test-registryitem -Path HKCU:\jdhit\powershell -name bogus
False
PS S:\> test-registryitem -Path HKCU:\jdhit\powershell -name test
True
[/cc]
This makes my scripting much more efficient.
[cc lang="PowerShell"]
if (-not (Test-registryitem -path HKCU:\jdhit\powershell -name blog))
{
new-itemproperty -path HKCU:\jdhit\powershell -name blog -value https://jdhitsolutions.com/blog
}
[/cc]
Download Test-RegistryItem.ps1.
Great post, this is exactly what I was looking for. What would you do if you had a whole slew of registry keys to test and you wanted some sort of report of what was compliant and what wasn’t? Ideally, I’d like to have the list of registry keys an external file that was read in when you run the script. That way it can change easily.
Thanks in advance!
Taking it a step further, can you also test the value of the registry key?
I have something in the works on this topic. Stay tuned.
How about remote machines? (without having to use remoting)
There are no registry cmdlets. You could write your own functions using the .NET registry classes, or even the WMI StdRegProvider, although the latter is notoriously poor performing remotely. Or take a look at http://code.msdn.microsoft.com/PSRemoteRegistry