Skip to content

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 use Get-ItemProperty/Set-ItemProperty/Remove-ItemProperty
  • HKLM: and HKCU: are pre-mapped PowerShell drives — no setup required
  • Writing to HKLM: requires an elevated (Administrator) session
  • Always -WhatIf and back up before changing anything under HKLM:\SYSTEM or HKLM:\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
Registry changes take effect immediately and there's no Recycle Bin. Export the key first with 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

if (Test-Path "HKLM:\SOFTWARE\MyApp") {
    Write-Output "MyApp is installed"
}
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"
On 64-bit Windows, 32-bit applications are redirected to 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.

Additional Resources