Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleaned up test and reformated readme #8

Merged
merged 2 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added

- Added module icon and Psd1 private data
- Quality Tests for functions and comment based help

### Changed

- Updated Icon png
- Changed `WisherTools.Helpers` to a RequiredModule module vs a nested module

Expand All @@ -27,7 +30,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added unit test skeletons for all public functions in the WinRegOps

### Changed

- Added 'WisherTools.Helpers' to Nested Modules
- Updated `build.yaml` to exclude `Modules/WisherTools.Helpers` from code coverage analysis.
- ### Changed
- Refactored `Open-RegistryKey` function to use new helper functions `Get-OpenBaseKey` and `Get-OpenRemoteBaseKey` to abstract static method calls for opening registry keys locally or remotely. This improves testability and modularity of the code.

- Updated `build.yaml` to exclude `Modules/WisherTools.Helpers` from code
coverage analysis.

- Refactored `Open-RegistryKey` function to use new helper functions `Get-OpenBaseKey`
and `Get-OpenRemoteBaseKey` to abstract static method calls for opening registry
keys locally or remotely. This improves testability and modularity of the code.
160 changes: 147 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,154 @@
# WinRegOps

The WinRegOps module provides a comprehensive set of PowerShell functions to interact with the Windows registry, offering a simplified interface for common operations such as reading, writing, and deleting registry keys and values. It acts as a wrapper around the Microsoft.Win32.RegistryKey .NET class, extending its functionality for both local and remote registry operations.
<p align="center">
<img src="https://raw.githubusercontent.com/LarryWisherMan/ModuleIcons/main/WinRegOps.png"
alt="WinRegOps Icon" width="400" />
</p>

The module is designed to handle tasks like retrieving specific registry values, exporting registry keys, managing subkeys, and removing keys with enhanced error handling. It allows for seamless interaction with the Windows registry across various environments and use cases, such as system configuration, profile management, and application settings.
The **WinRegOps** module provides a comprehensive set of PowerShell functions to
interact with the Windows registry, offering a simplified interface for common
operations such as reading, writing, deleting, and exporting registry keys and
values. It extends the functionality of the `Microsoft.Win32.RegistryKey` .NET
class and enables local and remote registry operations with enhanced error
handling.

This module can be used independently or as a dependency for higher-level management modules, offering flexibility and reliability in registry operations.
This module is designed to handle registry tasks such as retrieving specific
values, managing subkeys, and exporting registry keys. Whether performing
configuration management tasks on local machines or managing registry settings
across multiple remote systems, **WinRegOps** simplifies interaction with the
Windows registry.

Key features:
The module can be used independently or as a dependency for higher-level system
configuration or management modules, providing flexibility and reliability in
registry management operations.

- Open registry keys (local and remote).
- Query and retrieve registry values.
- Create, delete, and backup registry keys and subkeys.
- Built-in error handling for permission issues and remote access.
- Works with multiple registry hives (e.g., HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER).
---

Typical use cases include:
- Simplifying registry access in complex automation tasks.
- Providing a reliable registry management layer for other modules like ProfileManagement.
- Managing the lifecycle of registry keys during system configuration changes.
## **Key Features**

- **Open registry keys** on both local and remote machines using
`Get-OpenBaseKey` and `Get-OpenRemoteBaseKey`.
- **Query and retrieve registry values** using `Get-RegistryValue`.
- **Create, delete, and backup registry keys** and their subkeys with functions
like `New-RegistryKey`, `Remove-RegistrySubKey`, and `Backup-RegistryKey`.
- **Export registry keys** to files using the `reg.exe` utility, with the
`Export-RegistryKey` and `Invoke-RegCommand` functions.
- **Enhanced error handling** for permission issues and remote registry access.
- **Support for multiple registry hives**, such as `HKEY_LOCAL_MACHINE` and
`HKEY_CURRENT_USER`.

---

### **Typical Use Cases**

- **Automating system configuration**: Easily modify or retrieve registry
settings during system setup or maintenance tasks.
- **Profile and application management**: Use the module to configure profile
settings or manage application-specific registry values.
- **Registry backup and recovery**: Export critical registry keys before making
changes, ensuring that backups are available if needed.
- **Remote registry management**: Seamlessly access and modify registry keys on
remote systems without needing manual intervention.

---

### **Installation**

To install **WisherTools.Helpers**, you have two options:

1. **Install from PowerShell Gallery**
You can install the module directly from the [PowerShell Gallery](https://www.powershellgallery.com/packages/WinRegOps)
using the `Install-Module` command:

```powershell
Install-Module -Name WinRegOps
```

1. **Install from GitHub Releases**
You can also download the latest release from the [GitHub Releases page](https://github.com/LarryWisherMan/WinRegOps/releases).
Download the `.zip` file of the release, extract it, and place it in one of
your `$PSModulePath` directories.

---

### **Usage**

#### Example 1: Opening a Local Registry Key

Use the `Get-OpenBaseKey` function to open a registry hive on the local machine:

```powershell
$registryKey = Get-OpenBaseKey -RegistryHive 'HKEY_LOCAL_MACHINE'
```

This opens the `HKEY_LOCAL_MACHINE` hive on the local machine.

#### Example 2: Exporting a Registry Key

The `Export-RegistryKey` function allows you to export a registry key to a file
for backup purposes:

```powershell
Export-RegistryKey -RegistryPath "HKCU\Software\MyApp" -ExportPath "C:\Backup\MyApp.reg"
```

This exports the registry key `HKCU\Software\MyApp` to the file `C:\Backup\MyApp.reg`.

#### Example 3: Opening a Remote Registry Key

Use the `Get-OpenRemoteBaseKey` function to open a registry key on a remote
computer:

```powershell
$registryKey = Get-OpenRemoteBaseKey -RegistryHive 'HKEY_LOCAL_MACHINE' -ComputerName 'RemotePC'
```

This opens the `HKEY_LOCAL_MACHINE` hive on the remote computer `RemotePC`.

#### Example 4: Removing a Registry Subkey

You can remove a registry subkey using `Remove-RegistrySubKey`:

```powershell
$key = Open-RegistryKey -RegistryPath 'HKLM\Software'
Remove-RegistrySubKey -ParentKey $key -SubKeyName 'MyApp' -WhatIf
```

This will show what would happen if the `MyApp` subkey were deleted without
actually performing the deletion.

#### Example 5: Backing Up a Registry Key

The `Backup-RegistryKey` function allows you to back up a registry key to a
specified backup directory:

```powershell
Backup-RegistryKey -RegistryPath 'HKLM\Software\MyApp' -BackupDirectory 'C:\Backups'
```

This backs up the registry key `HKLM\Software\MyApp` to the `C:\Backups` directory.

---

### **Key Functions**

- **`Get-OpenBaseKey`**: Opens a registry hive on the local computer. Supports
both 32-bit and 64-bit views.
- **`Get-OpenRemoteBaseKey`**: Opens a registry hive on a remote computer.
Requires the remote registry service to be running.
- **`Get-RegistryValue`**: Retrieves a specific value from a registry key.
- **`Export-RegistryKey`**: Exports a registry key to a `.reg` file.
- **`Invoke-RegCommand`**: Executes a registry-related command using the `reg.exe`
utility. This function is used internally for registry exports and other commands.
- **`Backup-RegistryKey`**: Backs up a registry key from a local or remote
computer to a specified backup file.
- **`Remove-RegistrySubKey`**: Removes a subkey from a specified parent registry
key, supporting `-WhatIf` and `-Confirm` for safety.

---

### **Contributing**

Contributions are welcome! Feel free to fork this repository, submit pull
requests, or report issues. You can contribute by adding new features, improving
the existing code, or enhancing the documentation.
5 changes: 3 additions & 2 deletions build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Pester:
# Excludes one or more paths from being used to calculate code coverage.
ExcludeFromCodeCoverage:
- Modules/WisherTools.Helpers
- Holding/*

# If no scripts are defined the default is to use all the tests under the project's
# tests folder or source folder (if present). Test script paths can be defined to
Expand All @@ -103,8 +104,8 @@ Pester:
# - tests/Integration
ExcludeTag:
# - helpQuality
- FunctionalQuality
- TestQuality
#- FunctionalQuality
#- TestQuality
Tag:
CodeCoverageThreshold: 85 # Set to 0 to bypass
#CodeCoverageOutputFile: JaCoCo_$OsShortName.xml
Expand Down
89 changes: 89 additions & 0 deletions source/Holding/Invoke-RegCommandOld.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
function Invoke-RegCommand {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateSet("QUERY", "ADD", "DELETE", "COPY", "SAVE", "LOAD", "UNLOAD", "COMPARE", "EXPORT", "IMPORT", "RESTORE", "BACKUP", "RESTORE", "FLAGS")]
[string]$Operation,

[Parameter(Mandatory = $true)]
[string]$Path,

[string]$ValueName,

[string]$ValueData,

[ValidateSet("REG_SZ", "REG_DWORD", "REG_BINARY", "REG_MULTI_SZ", "REG_EXPAND_SZ")]
[string]$ValueType,

[string]$OutputFile,

[string]$ComputerName = $null,

[Switch]$PassThru
)

# Build argument list based on operation
$arguments = "$Operation `"$Path`""

if ($Operation -eq "EXPORT") {
if (-not $OutputFile) {
throw "You must specify an output file when using the EXPORT operation."
}
$arguments += " `"$OutputFile`" /y"
}
elseif ($ValueName) {
$arguments += " /v `"$ValueName`""
}

if ($ValueData) {
$arguments += " /d `"$ValueData`""
}

if ($ValueType) {
$arguments += " /t $ValueType"
}

# Local execution using Start-Process
if (-not $ComputerName) {
try {
Write-Verbose "Executing locally"
$processInfo = Start-Process -FilePath "reg.exe" -ArgumentList $arguments -NoNewWindow -PassThru -Wait
if ($processInfo.ExitCode -eq 0) {
Write-Host "Command executed successfully."
}
else {
Write-Error "Failed to execute reg command. Exit code: $($processInfo.ExitCode)"
}
}
catch {
Write-Error "Failed to execute reg command locally: $_"
}
}
else {
# Remote execution using Invoke-Command
try {
Write-Verbose "Executing remotely on $ComputerName"
$result = Invoke-Command -ComputerName $ComputerName -ScriptBlock {
param($operation, $path, $valueName, $valueData, $valueType, $outputFile)
$arguments = "$operation `"$path`""
if ($operation -eq "EXPORT") {
$arguments += " `"$outputFile`" /y"
}
elseif ($valueName) {
$arguments += " /v `"$valueName`""
}
if ($valueData) {
$arguments += " /d `"$valueData`""
}
if ($valueType) {
$arguments += " /t $valueType"
}

Start-Process -FilePath "reg.exe" -ArgumentList $arguments -NoNewWindow -Wait -PassThru
} -ArgumentList $Operation, $Path, $ValueName, $ValueData, $ValueType, $OutputFile
}
catch {
Write-Error "Failed to execute reg command on $ComputerName`: $_"
}
}
}
59 changes: 59 additions & 0 deletions source/Private/Invoke-RegCommand.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<#
.SYNOPSIS
Exports a specified registry key to a file using the `reg.exe` utility.

.DESCRIPTION
The `Invoke-RegCommand` function leverages the `reg.exe` command-line utility to export a specified registry key to a file. It accepts the registry path and export path as parameters, with default values provided by the environment variables `$ENV:Registry_Path` and `$ENV:Export_Path`. The function wraps this behavior in a PowerShell `Invoke-Command` call to execute the `reg.exe` command in the current session.

.PARAMETER RegistryPath
Specifies the path to the registry key that will be exported. If not provided, the function defaults to the value of the `$ENV:Registry_Path` environment variable.

.PARAMETER ExportPath
Specifies the file path where the registry export will be saved. If not provided, the function defaults to the value of the `$ENV:Export_Path` environment variable.

.EXAMPLE
Invoke-RegCommand -RegistryPath "HKCU\Software\MyKey" -ExportPath "C:\Export\mykey.reg"

This example exports the registry key `HKCU\Software\MyKey` to the file `C:\Export\mykey.reg`.

.EXAMPLE
$ENV:Registry_Path = "HKLM\Software\MyApp"
$ENV:Export_Path = "D:\Backup\myapp.reg"
Invoke-RegCommand

This example exports the registry key from the environment variable `Registry_Path` to the file path specified in `Export_Path`.

.NOTES
- The function requires the `reg.exe` utility, which is available on Windows operating systems by default.
- The registry and export paths can be passed as parameters or set via environment variables.
- Ensure the correct permissions are available for accessing the registry and writing to the specified output path.

#>

Function Invoke-RegCommand
{
param(
[string]$RegistryPath = $ENV:Registry_Path,
[string]$ExportPath = $ENV:Export_Path
)

$Parameters = @{
Operation = 'EXPORT'
Path = $RegistryPath
OutputFile = $ExportPath
}

if (-not [string]::IsNullOrEmpty($Parameters.Path) -and -not [string]::IsNullOrEmpty($Parameters.OutputFile))
{
$result = Invoke-Command -ScriptBlock {
param($Parameters)
&reg $Parameters.Operation $Parameters.Path $Parameters.OutputFile
} -ArgumentList $Parameters

return $result
}
else
{
throw "Path or OutputFile is null or empty."
}
}
Loading