Registry Operations
Note
Read and write Windows Registry keys and values safely using the Registry provider with Get-ItemProperty, Set-ItemProperty, New-Item, and Remove-Item.
Overview
PowerShell treats the Windows Registry as just another filesystem-like provider — the same *-Item and *-ItemProperty cmdlets you use on files and folders work on registry keys and values, using drive letters like HKLM: and HKCU: instead of C:. That consistency is convenient, but the Registry has real consequences: a bad write can break Windows or an application. Test everything with -WhatIf and back up keys you're about to change.
Basic Syntax
Get-ItemProperty -Path "HKLM:\SOFTWARE\MyApp"
Set-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -Name "Version" -Value "2.0"
New-Item -Path "HKLM:\SOFTWARE\MyApp" -Force
Remove-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -Name "OldSetting"
Key Points
- Registry keys (folders) use
Get-Item/New-Item/Remove-Item; registry values useGet-ItemProperty/Set-ItemProperty/Remove-ItemProperty HKLM:andHKCU:are pre-mapped PowerShell drives — no setup required- Writing to
HKLM:requires an elevated (Administrator) session - Always
-WhatIfand back up before changing anything underHKLM:\SYSTEMorHKLM:\SOFTWARE
Registry Drives
# List the pre-mapped registry drives
Get-PSDrive -PSProvider Registry
# HKEY_LOCAL_MACHINE - machine-wide settings
HKLM:
# HKEY_CURRENT_USER - settings for the logged-in user
HKCU:
# Less commonly used, not mapped by default - map them if needed
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT
New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS
Reading Registry Keys and Values
Listing Keys (Subkeys)
# List subkeys under a path (like Get-ChildItem for folders)
Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion"
# Recurse through subkeys
Get-ChildItem -Path "HKLM:\SOFTWARE\MyApp" -Recurse
Reading Values
# Get all values under a key
Get-ItemProperty -Path "HKLM:\SOFTWARE\MyApp"
# Get a single named value
(Get-ItemProperty -Path "HKLM:\SOFTWARE\MyApp").Version
# Get-ItemPropertyValue is more direct for a single value
Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\MyApp" -Name "Version"
# Check if a value exists before using it
$app = Get-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -ErrorAction SilentlyContinue
if ($app -and $app.PSObject.Properties.Name -contains "Version") {
$app.Version
}
Output:
Version : 2.0
InstallPath : C:\Program Files\MyApp
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\MyApp
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE
PSChildName : MyApp
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
Get-ItemProperty Output Includes Noise
Every registry value read includes PSPath, PSParentPath, PSChildName, PSDrive, and PSProvider properties that aren't real registry values — they're PowerShell provider metadata. Pipe through Select-Object -Property * -ExcludeProperty PS* or just reference the specific value name directly to avoid confusion.
Creating and Writing
Creating Keys
# Create a new key (like a folder)
New-Item -Path "HKLM:\SOFTWARE\MyApp" -Force
# Create nested keys in one call
New-Item -Path "HKLM:\SOFTWARE\MyCompany\MyApp\Settings" -Force
Setting Values
# Create or update a value under an existing key
Set-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -Name "Version" -Value "2.1"
# Set a DWORD (integer) value
Set-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -Name "MaxRetries" -Value 5
# New-ItemProperty explicitly specifies the value type
New-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -Name "Enabled" -Value 1 -PropertyType DWord -Force
Set-ItemProperty Creates If Missing
Set-ItemProperty will create the value if it doesn't already exist, so you don't strictly need New-ItemProperty unless you need to control the specific registry value type (String, DWord, QWord, Binary, MultiString, ExpandString).
Deleting Keys and Values
# Delete a single value (keeps the key)
Remove-ItemProperty -Path "HKLM:\SOFTWARE\MyApp" -Name "OldSetting"
# Delete an entire key (and everything under it if -Recurse)
Remove-Item -Path "HKLM:\SOFTWARE\MyApp\OldFeature" -Recurse -Force
# Always preview first
Remove-Item -Path "HKLM:\SOFTWARE\MyApp\OldFeature" -Recurse -WhatIf
There Is No Undo
# Deleting a key removes everything under it, permanently
Remove-Item -Path "HKLM:\SOFTWARE\MyApp" -Recurse -Force
reg export (or Get-ItemProperty piped to a file) if you might need to roll back. Common Read-Only Registry Tasks
# Check installed Windows version details
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" |
Select-Object ProductName, DisplayVersion, CurrentBuild
# List installed 64-bit applications (from Uninstall key)
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" |
Get-ItemProperty | Where-Object DisplayName |
Select-Object DisplayName, DisplayVersion, Publisher |
Sort-Object DisplayName
# Check a specific application's registered uninstall string
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" |
Get-ItemProperty | Where-Object { $_.DisplayName -like "*MyApp*" }
Important Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
-Path | String | Registry key path (HKLM:\...) | Get-Item -Path "HKLM:\SOFTWARE\MyApp" |
-Name | String | Value name | Set-ItemProperty -Name "Version" |
-Value | Object | Value data | Set-ItemProperty -Value "2.0" |
-PropertyType | String | New-ItemProperty: DWord, String, Binary, etc. | -PropertyType DWord |
-Recurse | Switch | Include subkeys | Remove-Item -Recurse |
-Force | Switch | Create parents, overwrite, suppress prompts | New-Item -Force |
-WhatIf | Switch | Preview without executing | Remove-Item -WhatIf |
Common Patterns
# Pattern 1: Safely check and read a value that might not exist
function Get-RegValue {
param([string]$Path, [string]$Name, $Default = $null)
$item = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue
if ($item) { $item.$Name } else { $Default }
}
Get-RegValue -Path "HKLM:\SOFTWARE\MyApp" -Name "Timeout" -Default 30
# Pattern 2: Ensure a key exists before writing to it
$keyPath = "HKLM:\SOFTWARE\MyCompany\MyApp"
if (-not (Test-Path $keyPath)) {
New-Item -Path $keyPath -Force | Out-Null
}
Set-ItemProperty -Path $keyPath -Name "Configured" -Value 1
# Pattern 3: Export a key's values before modifying (poor-man's backup)
$backup = Get-ItemProperty -Path "HKLM:\SOFTWARE\MyApp"
$backup | ConvertTo-Json | Set-Content -Path "C:\Backups\MyApp-registry-backup.json"
Real-World Examples
Example: Application Configuration Audit
Scenario: Verify a set of expected registry settings are configured correctly across an application's key, flagging anything missing or wrong.
$keyPath = "HKLM:\SOFTWARE\MyApp"
$expected = @{
Enabled = 1
MaxRetries = 5
LogLevel = "Info"
}
$actual = Get-ItemProperty -Path $keyPath -ErrorAction SilentlyContinue
foreach ($key in $expected.Keys) {
$expectedValue = $expected[$key]
$actualValue = if ($actual) { $actual.$key } else { $null }
if ($actualValue -ne $expectedValue) {
Write-Warning "Mismatch: $key expected '$expectedValue' but found '$actualValue'"
}
}
Explanation: Reading the whole key once with Get-ItemProperty avoids repeated registry hits, and comparing against a known-good hashtable makes configuration drift easy to spot in a single pass.
Tips & Tricks
Test-Path Works on Registry Paths Too
Since the Registry is a PowerShell provider,Test-Path, Join-Path, and Split-Path all work on registry paths exactly like they do on filesystem paths. 32-bit vs 64-bit Registry Redirection
# A 32-bit application's settings often live under Wow6432Node, not the path you'd expect
Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\MyApp"
HKLM:\SOFTWARE\WOW6432Node\.... If a key you expect to find under HKLM:\SOFTWARE\... isn't there, check WOW6432Node before assuming the app didn't write it. Related Topics
- Services Management - Many services store their configuration in the registry
- Path Operations - Test-Path, Join-Path work identically against registry paths