I got some nice feedback on my original Test-RegistryItem function. I had been mulling some enhancements anyway and now have a more robust version that looks at individual values, accepts pipelined input and more The new version now lets you test if a given registry item exists as well as if the value meets some target value. First, here's the new version, with comment help removed.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Function Test-RegistryItem { [cmdletbinding()] Param ( [Parameter(Position=0,Mandatory=$True, ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True, HelpMessage="Enter a registry path using the PSDrive format.")] [ValidateNotNullOrEmpty()] [Alias("PSPath")] [string]$Path, [Parameter(Position=1,Mandatory=$True, ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True, HelpMessage="Enter a registry key name.")] [ValidateNotNullOrEmpty()] [Alias("name","item")] [string]$Property, [Parameter()] [Alias("value")] [string]$TargetValue, [Switch]$UseTransaction ) Process { Write-Verbose ("Looking for {0} in {1}" -f $Property,$Path) if (Test-Path $path) { if ($UseTransaction) { $item=Get-ItemProperty -Path $path -Name $property -ErrorAction "SilentlyContinue" -UseTransaction } else { $item=Get-ItemProperty -Path $path -Name $property -ErrorAction "SilentlyContinue" } if ($item ) { #display the item if using -Verbose Write-Verbose ($item | select * | Out-String) $Exists=$True if ($TargetValue) { $ActualValue=$item.$Property Write-Verbose "Retrieving value for $Property" if ($ActualValue -eq $TargetValue) { $PropertyMatch=$True } else { $PropertyMatch=$False } } #if $value } #if $item else { Write-Verbose "Not found" $Exists=$False $PropertyMatch=$False } } #if test-path else { Write-Warning "Failed to find $path" $Exists=$False } #create a custom object $obj=New-Object -TypeName PSObject -Property @{ "Path"=$path "Property"=$Property "Exists"=$Exists } #add additional properties if looking for a property match if ($TargetValue) { Write-Verbose "Adding TargetValue Properties" $obj | Add-Member -MemberType NoteProperty -Name "PropertyMatch" -Value $PropertyMatch $obj | Add-Member -MemberType NoteProperty -Name "TargetValue" -Value $TargetValue $obj | Add-Member -MemberType NoteProperty -Name "ActualValue" -Value $ActualValue } #write the result to the pipeline write $obj } #end Process } #end function
The new version writes a custom object to the pipeline which provides more information. Let me walk through an example of the new version.
PS C:\> Test-RegistryItem -path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\WinLogon" -Property "AutoAdminLogon" -TargetValue 1
I want to see if the AutoAdminLogon item has a value of 1. The original part of the function that verifies the path is unchanged. But now if you specify a target value, the function checks to see if the current value matches the actual value.
if ($TargetValue) { $ActualValue=$item.$Property Write-Verbose "Retrieving value for $Property" if ($ActualValue -eq $TargetValue) { $PropertyMatch=$True } else { $PropertyMatch=$False }
A variable is defined to indicate if the values match. I also define $Exists since the item was found. After checking for the property value, the function creates a custom object with a few baseline properties.
#create a custom object $obj=New-Object -TypeName PSObject -Property @{ "Path"=$path "Property"=$Property "Exists"=$Exists }
If I hadn't been checking a specific property value, this object would have been written to the pipeline. But because I wanted to confirm a target value, a few additional properties are added to the object.
if ($TargetValue) { Write-Verbose "Adding TargetValue Properties" $obj | Add-Member -MemberType NoteProperty -Name "PropertyMatch" -Value $PropertyMatch $obj | Add-Member -MemberType NoteProperty -Name "TargetValue" -Value $TargetValue $obj | Add-Member -MemberType NoteProperty -Name "ActualValue" -Value $ActualValue }
I end up with a custom object like this.
Property : AutoAdminLogon Path : HKLM:\Software\Microsoft\Windows NT\CurrentVersion\WinLogon Exists : True PropertyMatch : False TargetValue : 1 ActualValue : 0
The function also takes pipelined input so I can quickly check to see what keys might be missing. And because I'm now writing an object to the pipeline I can easily filter my results.
PS C:\> import-csv winlogon.csv | test-registryitem | Where {-Not $_.Exists} Property Path Exists -------- ---- ------ FOODisableCAD HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon False FOOShutdownFlags HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon False
I hope you'll download the new version and let me know what you think. Oh..and that CSV file referenced in the last example? I've got that goody saved for another day.
Download Test-RegistryItem v2.0 here.