Test if registry value exists

PowershellRegistry

Powershell Problem Overview


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...

Powershell Solutions


Solution 1 - Powershell

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
        }
    }
}

Solution 2 - Powershell

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
    }
    
}

Solution 3 - Powershell

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.

Solution 4 - Powershell

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

Solution 5 - Powershell

One-liner:

$valueExists = (Get-Item $regKeyPath -EA Ignore).Property -contains $regValueName

Solution 6 - Powershell

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
}

Solution 7 - Powershell

$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"
}

Solution 8 - Powershell

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

Solution 9 - Powershell

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"
}

Solution 10 - Powershell

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
}

Solution 11 - Powershell

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}
}

Solution 12 - Powershell

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
    }
}

Solution 13 - Powershell

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
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNewanjaView Question on Stackoverflow
Solution 1 - PowershellJasonMArcherView Answer on Stackoverflow
Solution 2 - PowershellAaron JensenView Answer on Stackoverflow
Solution 3 - PowershellPaul WilliamsView Answer on Stackoverflow
Solution 4 - PowershellRoman KuzminView Answer on Stackoverflow
Solution 5 - PowershellBronxView Answer on Stackoverflow
Solution 6 - PowershellBacon BitsView Answer on Stackoverflow
Solution 7 - PowershellPedro LobitoView Answer on Stackoverflow
Solution 8 - PowershellPorkyView Answer on Stackoverflow
Solution 9 - PowershellTorbjörn BergstedtView Answer on Stackoverflow
Solution 10 - PowershellbraxlanView Answer on Stackoverflow
Solution 11 - Powershell4x0v7View Answer on Stackoverflow
Solution 12 - PowershellOcaso ProtalView Answer on Stackoverflow
Solution 13 - PowershellDavid VawterView Answer on Stackoverflow