Search code examples
powershellsyntaxregistry

Why does Test-Path not work on HKEY_LOCAL_MACHINE, but only HKLM:


I have found a behaviour in Powershell that looks very inconsistent and confusing to me, it is mainly about different notations when accessing registry keys, and what kind of syntax is expected (as an argument) or delivered (as a return value) by various commandlets, especially loke this:

HKEY_LOCAL_MACHINE... vs. HKLM:\

Let me show you an example:

$baseDir = "HKLM:\System\CurrentControlSet\Enum\SCSI"
$Results = Get-ChildItem $baseDir -Recurse -ErrorAction SilentlyContinue

foreach ($item in $Results)
{    
    $Subkey = $item.Name
    $keyExists = Test-Path "$Subkey" -PathType Container -ErrorAction SilentlyContinue
    if ($keyExists -eq $False) 
    {
        New-Item $Subkey            
    }
}

So what happens is the following:

$Subkey = $item.Name

returns HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\SCSI\SomePath

and

$keyExists = Test-Path "$Subkey" -PathType Container -ErrorAction SilentlyContinue

fails to work with that syntax, i.e. returns "$false" even though the path exists.

I have, as a workaround, entered the followng line of code between these two lines, which fixes the problem:

$Subkey = $Subkey -replace "HKEY_LOCAL_MACHINE", "HKLM:"

That works - it alters the string to: HKLM:\System\CurrentControlSet\Enum\SCSI\SomePath so Test-Path can work with that syntax, but it is not very elegant.

What am I actually missing? Why does powershell not return the Result-names from Get-ChildItem in a way that is suitable for further processing in powershell? Why not always use the same syntax style?

To me, this is a design flaw in Powershell, or is there any other way to fix that?

(Note: this is only a stripped-down example to show the basic problem, I know that it doesn't make sense to search for child items and check it's existence...)


Solution

  • HKLM: is a valid PSDrive while HKEY_LOCAL_MACHINE is not.

    PS C:\> Get-PSProvider Registry | select -Expand Drives
    
    Name  Used (GB)  Free (GB) Provider  Root                CurrentLocation
    ----  ---------  --------- --------  ----                ---------------
    HKLM                       Registry  HKEY_LOCAL_MACHINE
    HKCU                       Registry  HKEY_CURRENT_USER

    Use Test-Path on the items' PSPath property instead of their Name property.