Skip to main content
PowerShell · lesson 6 of 12
PowerShell intermediate Lesson 6 of 12

PSDrives and the Registry as a Filesystem

PowerShell's provider model makes the registry navigable with Get-ChildItem, cd, and Test-Path — except Get-ChildItem lists subkeys, not values, which looks like an empty key until you reach for Get-ItemProperty instead.

By SkillByExample · Published

powershell registry windows providers

cd works on the registry. That single fact is what PowerShell’s provider model buys you — and it’s also where the first gotcha in this lesson comes from.

Everything is a drive

Get-PSDrive | Select-Object Name, Provider
Name     Provider
----     --------
Alias    Microsoft.PowerShell.Core\Alias
C        Microsoft.PowerShell.Core\FileSystem
Cert     Microsoft.PowerShell.Security\Certificate
Env      Microsoft.PowerShell.Core\Environment
Function Microsoft.PowerShell.Core\Function
HKCU     Microsoft.PowerShell.Core\Registry
HKLM     Microsoft.PowerShell.Core\Registry
Temp     Microsoft.PowerShell.Core\FileSystem
Variable Microsoft.PowerShell.Core\Variable
WSMan    Microsoft.WSMan.Management\WSMan

C: and HKCU: are both just drives backed by different providers — one is the file system, one is the registry, and the same cmdlets (Get-ChildItem, Test-Path, Remove-Item) work against either. This is why HKCU: and HKLM: look exactly like drive letters: as far as the cmdlets are concerned, they are.

Creating and reading a value

New-Item -Path "HKCU:\Software\PowerShellLessonDemo" -Force | Out-Null
Set-ItemProperty -Path "HKCU:\Software\PowerShellLessonDemo" -Name "Environment" -Value "staging"

HKCU (the current user’s hive) is safe to write test keys into — it affects only this user account and needs no elevated permissions, unlike HKLM, which is machine-wide.

The bug: Get-ChildItem shows nothing

Get-ChildItem "HKCU:\Software\PowerShellLessonDemo"

Empty. Not an error — just nothing. The value was definitely set in the step above, so this looks like the write silently failed.

The fix: Get-ItemProperty reads values, not subkeys

Get-ItemProperty -Path "HKCU:\Software\PowerShellLessonDemo"
Environment  : staging
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\PowerShellLessonDemo
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software
PSChildName  : PowerShellLessonDemo
PSDrive      : HKCU
PSProvider   : Microsoft.PowerShell.Core\Registry

There it is. Get-ChildItem on a registry path lists child keys — the registry’s version of subfolders — and this key has none, so it correctly reported an empty list. The value lives directly on the key, and Get-ItemProperty is what reads that. This is the single most common point of confusion in scripting the registry: Get-ChildItem behaving like a real, working ls that just happens to always show nothing for a key with no subkeys of its own.

Real subkeys work with Get-ChildItem as expected

Get-ChildItem "HKCU:\Software" | Select-Object -First 5 -Property PSChildName
PSChildName
-----------
4kdownload.com
Adobe
Android Open Source Project
AOMEI
appdatalow

Every one of these is a subkey, so Get-ChildItem lists them correctly — the confusion only happens with a key’s own values, never with its child keys.

Cleanup

Remove-Item -Path "HKCU:\Software\PowerShellLessonDemo" -Force
Test-Path "HKCU:\Software\PowerShellLessonDemo"
False

Remove-Item on a registry key works exactly like deleting a file or folder — the same cmdlet, the same -Force, a different provider underneath.

Practice

1. Create a nested subkey, then list it correctly with Get-ChildItem.
New-Item -Path "HKCU:\Software\PowerShellLessonDemo" -Force | Out-Null
New-Item -Path "HKCU:\Software\PowerShellLessonDemo\SubKey" -Force | Out-Null
Get-ChildItem "HKCU:\Software\PowerShellLessonDemo" | Select-Object PSChildName
PSChildName
-----------
SubKey

This time Get-ChildItem finds something, because SubKey really is a child key — not a value sitting directly on the parent, which is exactly the distinction the bug above turned on.

2. Read a single named value directly with Get-ItemPropertyValue, skipping the wrapper object.
Set-ItemProperty -Path "HKCU:\Software\PowerShellLessonDemo" -Name "Environment" -Value "staging"
Get-ItemPropertyValue -Path "HKCU:\Software\PowerShellLessonDemo" -Name "Environment"
staging

No PSPath, no PSDrive, none of Get-ItemProperty’s metadata clutter — just the value itself, useful when a script only ever needs the one thing.

3. Try removing the demo tree without -Recurse first, then with it.
Remove-Item -Path "HKCU:\Software\PowerShellLessonDemo" -Force
Remove-Item: PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.

A key with a subkey and no -Recurse makes Remove-Item stop and ask “this has children, are you sure?” — in a script or a non-interactive session, there’s nothing to answer that prompt, so it errors out instead of guessing.

Remove-Item -Path "HKCU:\Software\PowerShellLessonDemo" -Recurse -Force
Test-Path "HKCU:\Software\PowerShellLessonDemo"
False

-Recurse answers that question up front — delete the key and everything under it, no prompt needed.

Next: error handling — terminating versus non-terminating errors, and why -ErrorAction Stop matters.

Frequently Asked Questions

Is this lesson's content Windows-only?
Yes — the registry provider (HKCU:, HKLM:) only exists on Windows, unlike the rest of this track, which runs on PowerShell 7 anywhere. The provider model itself (PSDrives backed by different data sources) is cross-platform; the registry is just one provider that happens to only make sense on Windows.
Why did Get-ChildItem show nothing for a registry key that clearly had a value set?
Get-ChildItem on a registry path lists child keys — the registry's version of subfolders — not the values stored directly on that key. A key with one value and no subkeys is, from Get-ChildItem's point of view, empty. Get-ItemProperty reads what's actually stored on the key itself, which is where the value shows up.
What's the difference between Get-ItemProperty and Get-ItemPropertyValue?
Get-ItemProperty returns an object with every value on the key as a property, plus several PS*-prefixed metadata properties (PSPath, PSParentPath, and so on) mixed in. Get-ItemPropertyValue skips straight to one named value with no wrapper object — useful when a script only needs the value itself, not the object it came wrapped in.
Why HKCU instead of HKLM for the examples in this lesson?
HKCU (HKEY_CURRENT_USER) only affects the current user's settings and needs no elevated permissions to write to — safe to create and delete test keys under. HKLM (HKEY_LOCAL_MACHINE) affects every user on the machine and usually requires administrator rights; treat it as read-mostly territory unless a script has a specific, deliberate reason to change machine-wide settings.
Are PSDrives only for the filesystem and registry?
No — Get-PSDrive lists every provider currently mounted, and Cert: (the certificate store) and Env: (environment variables) show up as drives the same way C: and HKCU: do. Any provider that implements the right interface can be navigated with the same cmdlets, which is the actual point of the provider model.