Проверьте, существует ли значение реестра - PullRequest
36 голосов
/ 13 апреля 2011

В моем скрипте powershell я создаю одну запись реестра для каждого элемента, для которого запускаю скрипт, и я хотел бы сохранить некоторую дополнительную информацию о каждом элементе в реестре (если вы указали необязательные параметры один раз, то по умолчанию эти параметры используются вбудущее).

Проблема, с которой я столкнулся, заключается в том, что мне нужно выполнить Test-RegistryValue (например, здесь ), но, похоже, он не работает (он возвращает false, даже еслизапись существует).Я попытался «построить на его основе», и единственное, что я придумал, это:

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

Это, к сожалению, также не делает то, что мне нужно, так как кажется, что он всегда выбирает некоторое (первое?) Значениеиз раздела реестра.

У кого-нибудь есть идеи, как это сделать?Просто кажется слишком много, чтобы написать управляемый код для этого ...

Ответы [ 12 ]

26 голосов
/ 13 апреля 2011

Лично мне не нравятся тестовые функции, которые могут выплевывать ошибки, поэтому вот что я хотел бы сделать. Эта функция также служит фильтром, который можно использовать для фильтрации списка ключей реестра, чтобы сохранить только те из них, которые имеют определенный ключ.

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
        }
    }
}
11 голосов
/ 06 сентября 2012

Модуль Carbon PowerShell имеет функцию Test-RegistryKeyValue , которая сделает эту проверку за вас.(Раскрытие информации: я владелец / сопровождающий Carbon.)

Сначала необходимо проверить, существует ли раздел реестра.Затем вы должны обработать, если ключ реестра не имеет значений.Большинство примеров здесь фактически проверяют само значение, а не существование значения.Это вернет ложные отрицания, если значение является пустым или нулевым.Вместо этого вы должны проверить, действительно ли существует свойство для значения в объекте, возвращаемом Get-ItemProperty.

Вот код, как он есть сегодня, из модуля Carbon:

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
    }

}
6 голосов
/ 13 апреля 2011

Я бы пошел с функцией Get-RegistryValue.Фактически он получает запрошенные значения (чтобы его можно было использовать не только для тестирования).Поскольку значения реестра не могут быть нулевыми, мы можем использовать нулевой результат как признак пропущенного значения.Также предоставляется функция чистого теста Test-RegistryValue.

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

ВЫХОД:

True
54
False
missing value
5 голосов
/ 13 апреля 2011

Вероятно проблема со строками, имеющими пробел. Вот исправленная версия, которая работает для меня:

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
}
4 голосов
/ 11 мая 2017

Лучший способ проверить, существует ли значение реестра, - это просто сделать это - проверить его существование. Это однострочный текст, даже если его немного сложно прочитать.

PS C:> (Get-ItemProperty $ regkey) .PSObject.Properties.Name -contains $ Имя

Если вы действительно посмотрите на данные , вы столкнетесь с усложнением интерпретации Powershell 0.

3 голосов
/ 28 февраля 2017

Однострочник:

$valueExists = (Get-Item $regKeyPath -EA Ignore).Property -contains $regValueName
1 голос
/ 09 июня 2016

Моя версия, совпадающая с точным текстом из пойманного исключения.Он вернет true, если это другое исключение, но работает для этого простого случая.Также Get-ItemPropertyValue является новым в 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}
}
1 голос
/ 25 августа 2015
$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"
}
0 голосов
/ 12 октября 2016

Я взял методологию из Carbon выше и упростил код до более мелкой функции, для меня это очень хорошо работает.

0 голосов
/ 16 февраля 2016

Моя версия:

Function Test-RegistryValue($Key, $Name)
{
    (Get-ChildItem (Split-Path -Parent -Path $Key) | Where-Object {$_.PSChildName -eq (Split-Path -Leaf $Key)}).Property -contains $Name
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...