2011-04-13 17 views
25

En mi script de powershell estoy creando una entrada de registro para cada elemento en el que ejecuto el script y me gustaría almacenar información adicional sobre cada elemento en el registro (si especifica parámetros opcionales una vez, entonces de forma predeterminada usa esos params en el futuro).Pruebe si existe valor de registro

El problema que he encontrado es que necesito realizar Test-RegistryValue (como here) pero no parece ser el truco (devuelve falso incluso si la entrada existe). Me trataron de "construir encima de ella" y lo único que se me ocurrió es la siguiente:

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

que, lamentablemente, también no hace lo que necesito, ya que parece que siempre selecciona algunos (por primera vez?) De valor la clave de registro

¿Alguien tiene idea de cómo hacer esto? Apenas se parece mucho a escribir código administrado para este ...

+1

'' '(Get-Item -path ruta $) .GetValue (valor de $) -ne $ null''' devuelve true si el valor existe. – dezza

Respuesta

21

Personalmente, no me gusta funciones de prueba que tienen la oportunidad de escupir errores, así que aquí es lo que haría. Esta función también funciona como un filtro que puede usar para filtrar una lista de claves de registro para conservar solo las que tienen una determinada clave.

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

Un error: '$ Key.GetValue ($ Name, $ null))' puede obtener 0 o una cadena vacía, es decir, existe un valor pero 'if ($ Key.GetValue ($ Name, $ null))) 'obtiene falso y el script devuelve falso, como si faltara un valor. Además, recomendaría usar '-LiteralPath' en lugar de' -Path' en todas partes. La tarea es sobre una prueba de valor único. Tenga en cuenta que '*' y '?' Son caracteres poco frecuentes pero válidos para los nombres de registro. –

+0

Bueno, puntos, lo arreglaron un poco. – JasonMArcher

0

La prueba -not debe disparar si una propiedad no existe:

$prop = (Get-ItemProperty $regkey).$name 
if (-not $prop) 
{ 
    New-ItemProperty -Path $regkey -Name $name -Value "X" 
} 
+1

Parece realmente que la solución vinculada fue correcta, pero por alguna razón invoqué la función usando sintaxis similar a C en lugar de pasar parámetros con nombre y así tanto $ regkey se inicializó con la concatenación de cadenas para $ regkey y $ name :( – Newanja

4

Me gustaría ir con la función Get-RegistryValue. De hecho, obtiene los valores solicitados (para que pueda usarse no solo para probar). En cuanto a los valores de registro no pueden ser nulos, podemos usar el resultado nulo como un signo de un valor perdido. También se proporciona la función de prueba pura 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 } 

SALIDA:

True 
54 
False 
missing value 
+0

A palabra sobre errores (incluso con los errores '-ErrorAction SilentlyContinue' en realidad se agregan a la lista' $ Error'). Suponiendo que verifiquemos los valores que faltan potencialmente de presumiblemente * existentes * claves no debería haber demasiados errores en la práctica. tales errores no son deseados, entonces el código debería verse como 'if (Test-Path -LiteralPath $ path) {...} else {...}'. –

+0

Yo voté y luego probé :) Fracasa con un simple ejemplo de prueba: $ regkey = "HKCU: \ Software \ Microsoft" $ name = "myName1" $ clave = Get-Item -LiteralPath $ ruta -ErrorAction en silencio Continuar ERROR: Get-Item: No se puede vincular el argumento al parámetro 'LiteralPath' porque es nulo. – Newanja

+0

Quizás ya haya encontrado su error tipográfico. Usted envía la variable '$ path' en' Get-Item'. Pero no está definido en su fragmento de código: usted define '$ regkey'. Entonces deberías hacer 'Get-Item -LiteralPath $ regkey'. –

0

Esto funciona para mí:

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

Probablemente un problema con cadenas que tienen espacios en blanco. He aquí una limpiado versión que funciona para mí:

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

Ejemplo de uso para cualquiera que lea: 'Test-RegistryValue" HKLM: \ SOFTWARE \ Classes \ Installer \ Dependencies \ {f65db027-aff3-4070-886a-0d87064aabb1} "" DisplayName "' – Luke

+0

'($ exists -ne $ null) - y ($ exists.Length -ne 0) 'falla cuando existe la propiedad. He encontrado que es mejor usar '(-not $ exists)' en su lugar – Luke

10

El Carbon PowerShell module tiene una función Test-RegistryKeyValue que va a hacer esta comprobación para usted. (Divulgación: soy el propietario/mantenedor de Carbon.)

Primero tiene que comprobar que la clave de registro existe. Luego debe manejar si la clave de registro no tiene valores. La mayoría de los ejemplos aquí en realidad están probando el valor en sí, en lugar de la existencia del valor. Esto devolverá falsos negativos si un valor está vacío o nulo. En su lugar, debe probar si realmente existe una propiedad para el valor en el objeto devuelto por Get-ItemProperty.

Aquí está el código, tal como está hoy, desde el módulo de carbono:

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 
    } 

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

Mi versión:

Function Test-RegistryValue($Key, $Name) 
{ 
    (Get-ChildItem (Split-Path -Parent -Path $Key) | Where-Object {$_.PSChildName -eq (Split-Path -Leaf $Key)}).Property -contains $Name 
} 
1

Mi versión, que coincide con el texto exacto de la excepción capturada. Devolverá verdadero si es una excepción diferente pero funciona para este caso simple. También Get-ItemPropertyValue es nuevo en 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} 
} 
0

Tomé la Metodología de carbono por encima, y ​​racionalizado el código en una función más pequeño, esto funciona muy bien para mí.

Function Test-RegistryValue($key,$name) 
    { 
     if(Get-Member -InputObject (Get-ItemProperty -Path $key) -Name $name) 
     { 
       return $true 
     } 
     return $false 
    } 
2

de una sola línea:

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

La mejor manera de probar si existe un valor del registro es para hacer precisamente eso - prueba de su existencia. Este es un trazador de líneas, incluso si es un poco difícil de leer.

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

Si realmente se ven hasta sus de datos, a continuación, se encuentra con la complicación de cómo interpreta Powershell 0.

Cuestiones relacionadas