-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added supporting methods like GetValueNames and GetValueKind (#12)
- Loading branch information
1 parent
c5f244c
commit 2381d96
Showing
8 changed files
with
424 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
function Update-JsonFile { | ||
param ( | ||
[Parameter(Mandatory = $true)] | ||
[string]$OutputFile, | ||
|
||
[Parameter(Mandatory = $true)] | ||
[array]$RegistryData # Generic data for registry keys | ||
) | ||
|
||
if (Test-Path $OutputFile) { | ||
$existingData = Get-Content -Path $OutputFile | ConvertFrom-Json | ||
$existingData += $RegistryData | ||
$existingData | ConvertTo-Json -Depth 10 | Set-Content -Path $OutputFile | ||
} else { | ||
$RegistryData | ConvertTo-Json -Depth 10 | Out-File -FilePath $OutputFile | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<# | ||
.SYNOPSIS | ||
Retrieves the value kind (type) of a specified registry key value. | ||
.DESCRIPTION | ||
This function wraps the RegistryKey.GetValueKind method to retrieve the type (kind) of a registry value. | ||
You can supply a base registry key and the value name. It returns the type of the value (e.g., String, DWord, Binary). | ||
.PARAMETER BaseKey | ||
The base registry key from which to retrieve the value kind. This should be an open RegistryKey object. | ||
.PARAMETER ValueName | ||
The name of the registry value for which to retrieve the kind. This is a required parameter. | ||
.OUTPUTS | ||
Microsoft.Win32.RegistryValueKind | ||
The type of the value (e.g., String, DWord, Binary). | ||
.EXAMPLE | ||
$baseKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\MyApp") | ||
Get-RegistryValueKind -BaseKey $baseKey -ValueName "Setting1" | ||
Description: | ||
Retrieves the kind (type) of the "Setting1" value from the "SOFTWARE\MyApp" registry key. | ||
.NOTES | ||
This function wraps around the .NET Framework's RegistryKey.GetValueKind method to make it easier to retrieve registry value types in PowerShell. | ||
#> | ||
|
||
function Get-RegistryValueKind | ||
{ | ||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Mandatory = $true, Position = 0)] | ||
[Microsoft.Win32.RegistryKey]$BaseKey, | ||
|
||
[Parameter(Mandatory = $true, Position = 1)] | ||
[string]$ValueName | ||
) | ||
|
||
try | ||
{ | ||
# Retrieve the kind (type) of the registry value | ||
return $BaseKey.GetValueKind($ValueName) | ||
} | ||
catch [System.Security.SecurityException] | ||
{ | ||
$errorMessage = "Access to the registry key is denied." | ||
throw [System.Security.SecurityException] $errorMessage | ||
} | ||
catch | ||
{ | ||
throw $_ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<# | ||
.SYNOPSIS | ||
Retrieves all the value names of a specified registry key. | ||
.DESCRIPTION | ||
This function wraps the RegistryKey.GetValueNames method to retrieve all the value names of a registry key. | ||
You can supply a base registry key, and the function will return an array of the value names present in the registry key. | ||
.PARAMETER BaseKey | ||
The base registry key from which to retrieve the value names. This should be an open RegistryKey object. | ||
.OUTPUTS | ||
String[] | ||
An array of strings representing the names of all the values stored in the registry key. | ||
.EXAMPLE | ||
$baseKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\MyApp") | ||
Get-RegistryValueNames -BaseKey $baseKey | ||
Description: | ||
Retrieves all the value names from the "SOFTWARE\MyApp" registry key. | ||
.NOTES | ||
This function wraps around the .NET Framework's RegistryKey.GetValueNames method to make it easier to retrieve value names in PowerShell. | ||
#> | ||
|
||
function Get-RegistryValueNames | ||
{ | ||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'The function name is appropriate.')] | ||
|
||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Mandatory = $true, Position = 0)] | ||
[Microsoft.Win32.RegistryKey]$BaseKey | ||
) | ||
|
||
try | ||
{ | ||
# Retrieve all the value names in the registry key | ||
return $BaseKey.GetValueNames() | ||
} | ||
catch [System.Security.SecurityException] | ||
{ | ||
$errorMessage = "Access to the registry key is denied." | ||
throw [System.Security.SecurityException] $errorMessage | ||
} | ||
catch | ||
{ | ||
throw $_ | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
<# | ||
.SYNOPSIS | ||
Creates a custom object representing the values of a registry key or subkey. | ||
.DESCRIPTION | ||
The New-RegistryKeyValuesObject function retrieves all the values of a specified registry key or subkey and returns a custom object containing the registry path, backup date, user, computer name, and the key's values. | ||
This function is flexible, allowing you to specify a subkey within the registry key, or work with the root key itself. Each value is stored along with its data type. | ||
.PARAMETER RegistryKey | ||
The base registry key to be queried. This parameter is mandatory and must be a valid `Microsoft.Win32.RegistryKey` object. | ||
.PARAMETER SubKeyName | ||
The name of the optional subkey within the `RegistryKey`. If provided, the function will operate on this subkey. If not provided, it will operate on the root registry key. | ||
.PARAMETER User | ||
The username of the individual performing the backup. Defaults to the current user's name from `$env:USERNAME`. | ||
.PARAMETER ComputerName | ||
The name of the computer where the registry key resides. Defaults to the current computer name from `$env:COMPUTERNAME`. | ||
.OUTPUTS | ||
PSCustomObject | ||
Returns a custom object with the following properties: | ||
- RegistryPath: The full path of the registry key or subkey. | ||
- BackupDate: The date and time of the backup. | ||
- ByUser: The username of the individual performing the backup. | ||
- ComputerName: The name of the computer. | ||
- Values: A dictionary of all the values within the registry key, where each entry contains: | ||
- Value: The data stored in the registry key value. | ||
- Type: The data type of the registry value (e.g., String, DWord, Binary). | ||
.EXAMPLE | ||
# Example 1: Export values from the root registry key | ||
$remoteRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, "RemotePC") | ||
$registryKey = $remoteRegistry.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList") | ||
$registryData = New-RegistryKeyValuesObject -RegistryKey $registryKey | ||
This example opens the `ProfileList` key on a remote computer and exports the values to a custom object. | ||
.EXAMPLE | ||
# Example 2: Export values from a specific subkey | ||
$remoteRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, "RemotePC") | ||
$registryKey = $remoteRegistry.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList") | ||
$registryData = New-RegistryKeyValuesObject -RegistryKey $registryKey -SubKeyName "S-1-5-21-12345" | ||
This example exports the values from a specific subkey (`S-1-5-21-12345`) within the `ProfileList` key on a remote computer. | ||
.NOTES | ||
- The function is useful for backing up registry data or auditing changes within a registry key. | ||
- Ensure that you have appropriate permissions to access the registry keys. | ||
.LINK | ||
https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.registrykey?view=net-8.0 | ||
#> | ||
|
||
function New-RegistryKeyValuesObject | ||
{ | ||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'No state changes are made in this function.')] | ||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Mandatory = $true)] | ||
[Microsoft.Win32.RegistryKey]$RegistryKey, # Generic registry key | ||
|
||
[string]$SubKeyName, # Optional subkey name within the registry key | ||
|
||
[string]$User = $env:USERNAME, | ||
|
||
[string]$ComputerName = $env:COMPUTERNAME | ||
) | ||
|
||
# Automatically set RegistryPath to the name of the registry key or subkey if provided | ||
if ($SubKeyName) | ||
{ | ||
$subKey = Get-RegistrySubKey -BaseKey $RegistryKey -Name $SubKeyName -writable $false | ||
$RegistryPath = $subKey.Name | ||
$selectedKey = $subKey | ||
} | ||
else | ||
{ | ||
$RegistryPath = $RegistryKey.Name | ||
$selectedKey = $RegistryKey | ||
} | ||
|
||
# Create the registry data object | ||
$registryData = [PSCustomObject]@{ | ||
RegistryPath = $RegistryPath | ||
BackupDate = Get-Date | ||
ByUser = $User | ||
ComputerName = $ComputerName | ||
Values = @{} | ||
} | ||
|
||
# Collect all value names and types from the subkey or root key | ||
foreach ($valueName in (Get-RegistryValueNames -baseKey $selectedKey)) | ||
{ | ||
$value = Get-RegistryValue -BaseKey $selectedKey -ValueName $valueName | ||
$valueType = (Get-RegistryValueKind -BaseKey $selectedKey -ValueName $valueName).tostring() | ||
$registryData.Values[$valueName] = @{ | ||
Value = $value | ||
Type = $valueType | ||
} | ||
} | ||
|
||
return $registryData | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
BeforeAll { | ||
$script:dscModuleName = "WinRegOps" | ||
|
||
# Import the module containing the registry functions | ||
Import-Module -Name $script:dscModuleName | ||
|
||
$PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName | ||
$PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName | ||
$PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName | ||
} | ||
|
||
AfterAll { | ||
$PSDefaultParameterValues.Remove('InModuleScope:ModuleName') | ||
$PSDefaultParameterValues.Remove('Mock:ModuleName') | ||
$PSDefaultParameterValues.Remove('Should:ModuleName') | ||
|
||
# Unload the module being tested so that it doesn't impact any other tests. | ||
Get-Module -Name $script:dscModuleName -All | Remove-Module -Force | ||
} | ||
|
||
Describe 'Get-RegistryValueKind Function Tests' -Tag 'Public' { | ||
Context 'When retrieving the kind of a registry value using New-MockObject' { | ||
# Mock the registry key object and the GetValueKind method | ||
|
||
It 'Should return the correct value kind (DWord) for the specified value name' { | ||
|
||
$mockBaseKey = New-MockObject -Type Microsoft.Win32.RegistryKey -Methods @{ | ||
GetValueKind = { return [Microsoft.Win32.RegistryValueKind]::DWord } | ||
} | ||
|
||
# Arrange | ||
$mockValueName = 'TestValue' | ||
|
||
# Act | ||
$result = Get-RegistryValueKind -BaseKey $mockBaseKey -ValueName $mockValueName | ||
|
||
# Assert | ||
$result | Should -BeOfType 'Microsoft.Win32.RegistryValueKind' | ||
$result | Should -Be 'DWord' | ||
} | ||
|
||
It 'Should throw a SecurityException if access is denied' { | ||
# Arrange: Mock the behavior for a security exception | ||
$mockBaseKey = New-MockObject -Type Microsoft.Win32.RegistryKey -Methods @{ | ||
GetValueKind = { throw [System.Security.SecurityException] "Access to the registry key is denied." } | ||
} | ||
$mockValueName = 'TestValue' | ||
|
||
# Act & Assert | ||
{ Get-RegistryValueKind -BaseKey $mockBaseKey -ValueName $mockValueName } | Should -Throw 'Exception calling "GetValueKind" with "1" argument(s): "Access to the registry key is denied."' | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
BeforeAll { | ||
$script:dscModuleName = "WinRegOps" | ||
|
||
# Import the module containing the registry functions | ||
Import-Module -Name $script:dscModuleName | ||
|
||
$PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName | ||
$PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName | ||
$PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName | ||
} | ||
|
||
AfterAll { | ||
$PSDefaultParameterValues.Remove('InModuleScope:ModuleName') | ||
$PSDefaultParameterValues.Remove('Mock:ModuleName') | ||
$PSDefaultParameterValues.Remove('Should:ModuleName') | ||
|
||
# Unload the module being tested so that it doesn't impact any other tests. | ||
Get-Module -Name $script:dscModuleName -All | Remove-Module -Force | ||
} | ||
|
||
Describe 'Get-RegistryValueNames Function Tests' -Tag 'Public' { | ||
Context 'When retrieving all value names from a registry key using New-MockObject' { | ||
|
||
It 'Should return all the value names from the registry key' { | ||
# Mock the registry key object and the GetValueNames method | ||
$mockBaseKey = New-MockObject -Type Microsoft.Win32.RegistryKey -Methods @{ | ||
GetValueNames = { return @('Value1', 'Value2', 'Value3') } | ||
} | ||
|
||
# Arrange | ||
# No additional arrangements needed | ||
|
||
# Act | ||
$result = Get-RegistryValueNames -BaseKey $mockBaseKey | ||
# Assert | ||
$result | Should -BeOfType [string] | ||
$result | Should -Contain 'Value1' | ||
$result | Should -Contain 'Value2' | ||
$result | Should -Contain 'Value3' | ||
} | ||
|
||
It 'Should throw a SecurityException if access is denied' { | ||
# Mock the registry key object and the GetValueNames method to throw a SecurityException | ||
$mockBaseKey = New-MockObject -Type Microsoft.Win32.RegistryKey -Methods @{ | ||
GetValueNames = { throw [System.Security.SecurityException] "Access to the registry key is denied." } | ||
} | ||
|
||
# Act & Assert | ||
{ Get-RegistryValueNames -BaseKey $mockBaseKey } | Should -Throw 'Exception calling "GetValueNames" with "0" argument(s): "Access to the registry key is denied."' | ||
} | ||
} | ||
} |
Oops, something went wrong.