私のPowerShellスクリプトでは、スクリプトを実行する要素ごとに1つのレジストリエントリを作成しています。各要素に関する追加情報をレジストリに保存したいと思います(オプションのパラメータを一度指定すると、デフォルトでそれらのパラメータを将来使用します)。
私が遭遇した問題は、Test-RegistryValueを実行する必要があることです( here など)が、トリックを実行していないようです(エントリが存在しても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
}
}
残念ながら、レジストリキーから常に(最初の?)値を選択するように見えるので、私は必要なことを行いません。
誰もこれを行う方法を知っていますか?このためにマネージコードを記述するのは多すぎるようです...
個人的には、エラーを吐き出す可能性のあるテスト関数が好きではないので、ここに私がすることを示します。この関数は、特定のキーを持つもののみを保持するためにレジストリキーのリストをフィルタリングするために使用できるフィルターとしても機能します。
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
}
}
}
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
}
}
関数Get-RegistryValue
。実際には、要求された値を取得します(テストだけでなく使用できるように)。レジストリ値をnullにできない限り、nullの結果を欠損値のサインとして使用できます。純粋なテスト関数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
レジストリ値が存在するかどうかをテストする最善の方法は、その-その存在をテストすることです。これは、読みにくい。
PS C:>(Get-ItemProperty $ regkey).PSObject.Properties.Name -contains $ name
実際にそのdataを調べると、Powershellが0を解釈する方法が複雑になります。
おそらく空白を含む文字列の問題。これは私のために働くクリーンアップされたバージョンです:
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
}
一発ギャグ:
$valueExists = (Get-Item $regKeyPath -EA Ignore).Property -contains $regValueName
キャッチされた例外からの正確なテキストと一致する私のバージョン。別の例外の場合は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}
}
$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"
}
私のバージョン:
Function Test-RegistryValue($Key, $Name)
{
(Get-ChildItem (Split-Path -Parent -Path $Key) | Where-Object {$_.PSChildName -eq (Split-Path -Leaf $Key)}).Property -contains $Name
}
これは私のために働く:
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
}
}
上記の方法論をCarbonから取得し、コードをより小さな関数に簡素化しました。これは非常にうまく機能します。
Function Test-RegistryValue($key,$name)
{
if(Get-Member -InputObject (Get-ItemProperty -Path $key) -Name $name)
{
return $true
}
return $false
}
-not
プロパティが存在しない場合、テストを起動する必要があります。
$prop = (Get-ItemProperty $regkey).$name
if (-not $prop)
{
New-ItemProperty -Path $regkey -Name $name -Value "X"
}