Newanja
Newanja

Reputation: 691

Test if registry value exists

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

Answers (13)

Torbjörn Bergstedt
Torbjörn Bergstedt

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

Paul Williams
Paul Williams

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

Pedro Lobito
Pedro Lobito

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

Porky
Porky

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

Bronx
Bronx

Reputation: 768

One-liner:

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

Upvotes: 13

David Vawter
David Vawter

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

4x0v7
4x0v7

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

Aaron Jensen
Aaron Jensen

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

braxlan
braxlan

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

JasonMArcher
JasonMArcher

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

Bacon Bits
Bacon Bits

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

Ocaso Protal
Ocaso Protal

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

Roman Kuzmin
Roman Kuzmin

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

Related Questions