Skip to content

Instantly share code, notes, and snippets.

@homotechsual
Last active January 30, 2025 16:07
Show Gist options
  • Save homotechsual/aa30b5d8e0873aa11adb7968df38cf7b to your computer and use it in GitHub Desktop.
Save homotechsual/aa30b5d8e0873aa11adb7968df38cf7b to your computer and use it in GitHub Desktop.
Utils.Registry.ShouldBe.ps1
# Utility Function: Registry.ShouldBe
## This function is used to ensure that a registry value exists and is set to a specific value.
function Registry.ShouldBe {
[CmdletBinding(DefaultParameterSetName = 'Named')]
param(
# The registry path to the key.
[Parameter(Mandatory, ParameterSetName = 'Named')]
[Parameter(Mandatory, ParameterSetName = 'Default')]
[String]$Path,
# The name of the registry value.
[Parameter(Mandatory, ParameterSetName = 'Named')]
[String]$Name,
# The value to set the registry value to.
[Parameter(Mandatory, ParameterSetName = 'Named')]
[Parameter(Mandatory, ParameterSetName = 'Default')]
[Object]$Value,
# The type of the registry value.
[Parameter(Mandatory, ParameterSetName = 'Named')]
[Parameter(Mandatory, ParameterSetName = 'Default')]
[ValidateSet('String', 'ExpandString', 'Binary', 'DWord', 'MultiString', 'QWord', 'None')]
[Microsoft.Win32.RegistryValueKind]$Type,
# Don't confirm that the registry value was set correctly.
[Parameter(ParameterSetName = 'Named')]
[Parameter(ParameterSetName = 'Default')]
[Switch]$SkipConfirmation,
# Don't alter the registry value - just check if it exists and is correct.
[Parameter(ParameterSetName = 'Named')]
[Parameter(ParameterSetName = 'Default')]
[Switch]$CheckOnly,
# Use 'Default' parameter set if no name is provided.
[Parameter(Mandatory, ParameterSetName = 'Default')]
[Switch]$DefaultMode
)
begin {
# Make sure the registry path exists.
if (!(Test-Path $Path)) {
Write-Warning ("Registry path '$Path' does not exist. Creating.")
New-Item -Path $Path -Force | Out-Null
}
# Make sure it's actually a registry path.
if (!(Get-Item $Path).PSProvider.Name -eq 'Registry' -and !(Get-Item $Path).PSIsContainer) {
throw "Path '$Path' is not a registry path."
}
$LoopCount = 0
if ($SkipConfirmation -and $CheckOnly) {
throw "Cannot use both 'SkipConfirmation' and 'CheckOnly' switches."
}
$CheckFailed = 0
}
process {
if ($Name) {
do {
# Handle named registry values.
# Make sure the registry value exists.
if (!(Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue)) {
Write-Warning ("Registry value '$Name' in path '$Path' does not exist.")
if (!$CheckOnly) {
Write-Warning ("Setting to '$Value'.")
New-ItemProperty -Path $Path -Name $Name -Value $Value -Force -Type $Type | Out-Null
} else {
Write-Warning ("Expected '$Name' to exist.")
$CheckFailed += 1
}
}
# Make sure the registry value type is correct. Skip if it's a None type.
if ($Type -ne [Microsoft.Win32.RegistryValueKind]::None) {
if ((Get-Item -Path $Path).GetValueKind($Name) -ne $Type) {
Write-Warning ("Registry value '$Name' in path '$Path' is not of type '$Type'.")
if (!$CheckOnly) {
Write-Warning ("Resetting to '$Type', '$Value'.")
Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type
} else {
Write-Warning ("Expected '$Name' to be type '$Type'.")
$CheckFailed += 1
}
}
}
# Make sure the registry value is correct.
if (!$SkipConfirmation) {
if ((Get-ItemProperty -Path $Path -Name $Name).$Name -ne $Value) {
Write-Warning ("Registry value '$Name' in path '$Path' is not correct.")
if (!$CheckOnly) {
Write-Warning ("Setting to '$Value'.")
Set-ItemProperty -Path $Path -Name $Name -Value $Value
} else {
Write-Warning ("Expected '$Name' to have value '$Value'.")
$CheckFailed += 1
}
}
$LoopCount++
} else {
# Short circuit the loop if we're skipping confirmation.
$LoopCount = 3
}
} while ((Get-ItemProperty -Path $Path -Name $Name).$Name -ne $Value -and $LoopCount -lt 3)
} else {
do {
# Handle default registry values.
# Make sure the registry value exists.
$RegistryValue = Get-ItemProperty -Path $Path -ErrorAction SilentlyContinue
if (!$RegistryValue -or !$RegistryValue.'(default)') {
Write-Warning ("Registry value in path '$Path' does not exist.")
if (!$CheckOnly) {
Write-Warning ("Setting to '$Value'.")
New-ItemProperty -Path $Path -Value $Value -Force -Type $Type | Out-Null
} else {
Write-Warning ("Expected '(default)' to exist.")
$CheckFailed += 1
}
}
# Make sure the registry value type is correct. Skip if it's a None type.
if ($Type -ne [Microsoft.Win32.RegistryValueKind]::None) {
if ((Get-Item -Path $Path).GetValueKind('') -ne $Type) {
Write-Warning ("Registry value in path '$Path' is not of type '$Type'.")
if (!$CheckOnly) {
Write-Warning ("Resetting to '$Type', '$Value'.")
Set-ItemProperty -Path $Path -Value $Value -Type $Type
} else {
Write-Warning ("Expected '(default)' to be type '$Type'.")
$CheckFailed += 1
}
}
}
# Make sure the registry value is correct.
if (!$SkipConfirmation) {
if ((Get-ItemProperty -Path $Path).'(default)' -ne $Value) {
Write-Warning ("Registry value in path '$Path' is not correct.")
if (!$CheckOnly) {
Write-Warning ("Setting to '$Value'.")
Set-ItemProperty -Path $Path -Value $Value
} else {
Write-Warning ("Expected '(default)' to have value '$Value'.")
$CheckFailed += 1
}
}
$LoopCount++
} else {
# Short circuit the loop if we're skipping confirmation.
$LoopCount = 3
}
} while ((Get-ItemProperty -Path $Path).'(default)' -ne $Value -and $LoopCount -lt 3)
}
if ($CheckFailed -ge 1) {
Write-Warning ("Registry key in path '$Path' is not correct.")
exit $CheckFailed
} else {
Write-Verbose ("Registry key in path '$Path' is correct.")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment