Reputation: 691
In my powershell script I'm creating one registry entry for each element I run script on and I would like to store some additional info about each element in registry (if you specify optional parameters once then by default use those params in the future).
The problem I've encountered is that I need to perform Test-RegistryValue (like here--see comment) but it doesn't seem to do the trick (it returns false even if entry exists). I tried to "build on top of it" and only thing I came up is this:
Function Test-RegistryValue($regkey, $name)
{
try
{
$exists = Get-ItemProperty $regkey $name -ErrorAction SilentlyContinue
Write-Host "Test-RegistryValue: $exists"
if (($exists -eq $null) -or ($exists.Length -eq 0))
{
return $false
}
else
{
return $true
}
}
catch
{
return $false
}
}
That unfortunately also doesn't do what I need as it seems it always selects some (first?) value from the registry key.
Anyone has idea how to do this? It just seems too much to write managed code for this...
Upvotes: 56
Views: 289340
Reputation: 3429
If StrictMode version 2 or greater is not enabled, the -not
test should fire if a property doesn't exist:
$prop = (Get-ItemProperty $regkey).$name
if (-not $prop)
{
New-ItemProperty -Path $regkey -Name $name -Value "X"
}
(If StrictMode version 2 or greater is enabled, the code will fail with an error if the $name does not already exist.)
Upvotes: 0
Reputation: 3357
The best way to test if a registry value exists is to do just that - test for its existence. This is a one-liner, even if it's a little hard to read.
(Get-ItemProperty $regkey).PSObject.Properties.Name -contains $name
If you actually look up its data, then you run into the complication of how Powershell interprets 0.
Upvotes: 23
Reputation: 98961
$regkeypath= "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
$value1 = (Get-ItemProperty $regkeypath -ErrorAction SilentlyContinue).Zoiper -eq $null
If ($value1 -eq $False) {
Write-Host "Value Exist"
} Else {
Write-Host "The value does not exist"
}
Upvotes: 3
Reputation: 988
If you are simply interested to know whether a registry value is present or not then how about:
[bool]((Get-itemproperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").PathName)
will return: $true while
[bool]((Get-itemproperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ValueNotThere)
will return: $false as it's not there ;)
You could adapt it into a scriptblock like:
$CheckForRegValue = { Param([String]$KeyPath, [String]$KeyValue)
return [bool]((Get-itemproperty -Path $KeyPath).$KeyValue) }
and then just call it by:
& $CheckForRegValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" PathName
Have fun,
Porky
Upvotes: 2
Reputation: 768
One-liner:
$valueExists = (Get-Item $regKeyPath -EA Ignore).Property -contains $regValueName
Upvotes: 13
Reputation: 41
I took the Methodology from Carbon above, and streamlined the code into a smaller function, this works very well for me.
Function Test-RegistryValue($key,$name)
{
if(Get-Member -InputObject (Get-ItemProperty -Path $key) -Name $name)
{
return $true
}
return $false
}
Upvotes: -1
Reputation: 9
My version, matching the exact text from the caught exception. It will return true if it's a different exception but works for this simple case. Also Get-ItemPropertyValue is new in PS 5.0
Function Test-RegValExists($Path, $Value){
$ee = @() # Exception catcher
try{
Get-ItemPropertyValue -Path $Path -Name $Value | Out-Null
}
catch{$ee += $_}
if ($ee.Exception.Message -match "Property $Value does not exist"){return $false}
else {return $true}
}
Upvotes: 0
Reputation: 26759
The Carbon PowerShell module has a Test-RegistryKeyValue function that will do this check for you. (Disclosure: I am the owner/maintainer of Carbon.)
You have to check that that the registry key exists, first. You then have to handle if the registry key has no values. Most of the examples here are actually testing the value itself, instead of the existence of the value. This will return false negatives if a value is empty or null. Instead, you have to test if a property for the value actually exists on the object returned by Get-ItemProperty
.
Here's the code, as it stands today, from the Carbon module:
function Test-RegistryKeyValue
{
<#
.SYNOPSIS
Tests if a registry value exists.
.DESCRIPTION
The usual ways for checking if a registry value exists don't handle when a value simply has an empty or null value. This function actually checks if a key has a value with a given name.
.EXAMPLE
Test-RegistryKeyValue -Path 'hklm:\Software\Carbon\Test' -Name 'Title'
Returns `True` if `hklm:\Software\Carbon\Test` contains a value named 'Title'. `False` otherwise.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the registry key where the value should be set. Will be created if it doesn't exist.
$Path,
[Parameter(Mandatory=$true)]
[string]
# The name of the value being set.
$Name
)
if( -not (Test-Path -Path $Path -PathType Container) )
{
return $false
}
$properties = Get-ItemProperty -Path $Path
if( -not $properties )
{
return $false
}
$member = Get-Member -InputObject $properties -Name $Name
if( $member )
{
return $true
}
else
{
return $false
}
}
Upvotes: 17
Reputation: 3
My version:
Function Test-RegistryValue($Key, $Name)
{
(Get-ChildItem (Split-Path -Parent -Path $Key) | Where-Object {$_.PSChildName -eq (Split-Path -Leaf $Key)}).Property -contains $Name
}
Upvotes: 0
Reputation: 15011
Personally, I do not like test functions having a chance of spitting out errors, so here is what I would do. This function also doubles as a filter that you can use to filter a list of registry keys to only keep the ones that have a certain key.
Function Test-RegistryValue {
param(
[Alias("PSPath")]
[Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[String]$Path
,
[Parameter(Position = 1, Mandatory = $true)]
[String]$Name
,
[Switch]$PassThru
)
process {
if (Test-Path $Path) {
$Key = Get-Item -LiteralPath $Path
if ($Key.GetValue($Name, $null) -ne $null) {
if ($PassThru) {
Get-ItemProperty $Path $Name
} else {
$true
}
} else {
$false
}
} else {
$false
}
}
}
Upvotes: 37
Reputation: 32180
Probably an issue with strings having whitespace. Here's a cleaned up version that works for me:
Function Test-RegistryValue($regkey, $name) {
$exists = Get-ItemProperty -Path "$regkey" -Name "$name" -ErrorAction SilentlyContinue
If (($exists -ne $null) -and ($exists.Length -ne 0)) {
Return $true
}
Return $false
}
Upvotes: 5
Reputation: 20257
This works for me:
Function Test-RegistryValue
{
param($regkey, $name)
$exists = Get-ItemProperty "$regkey\$name" -ErrorAction SilentlyContinue
Write-Host "Test-RegistryValue: $exists"
if (($exists -eq $null) -or ($exists.Length -eq 0))
{
return $false
}
else
{
return $true
}
}
Upvotes: -1
Reputation: 42063
I would go with the function Get-RegistryValue
. In fact it gets requested values (so that it can be used not only for testing). As far as registry values cannot be null, we can use null result as a sign of a missing value. The pure test function Test-RegistryValue
is also provided.
# This function just gets $true or $false
function Test-RegistryValue($path, $name)
{
$key = Get-Item -LiteralPath $path -ErrorAction SilentlyContinue
$key -and $null -ne $key.GetValue($name, $null)
}
# Gets the specified registry value or $null if it is missing
function Get-RegistryValue($path, $name)
{
$key = Get-Item -LiteralPath $path -ErrorAction SilentlyContinue
if ($key) {
$key.GetValue($name, $null)
}
}
# Test existing value
Test-RegistryValue HKCU:\Console FontFamily
$val = Get-RegistryValue HKCU:\Console FontFamily
if ($val -eq $null) { 'missing value' } else { $val }
# Test missing value
Test-RegistryValue HKCU:\Console missing
$val = Get-RegistryValue HKCU:\Console missing
if ($val -eq $null) { 'missing value' } else { $val }
OUTPUT:
True
54
False
missing value
Upvotes: 9