# ** careful "\" and "/" **
# initialization
New-Item 'registry::HKEY_CURRENT_USER/test'
New-ItemProperty 'registry::HKEY_CURRENT_USER\test' -Name test1 -Value test1
# read item.
Get-Item 'registry::HKEY_CURRENT_USER/test'
Set-ItemProperty 'registry::HKEY_CURRENT_USER/test' -Name test2 -Value abcde
# read and create item
Copy-Item 'registry::HKEY_CURRENT_USER/test' 'registry::HKEY_CURRENT_USER/test/t1'
Copy-Item 'registry::HKEY_CURRENT_USER\test' 'registry::HKEY_CURRENT_USER/test/t1'
# clear
Remove-Item 'registry::HKEY_CURRENT_USER\test' -Recurse -Force
no errors
Get-Item : Cannot find path 'HKEY_CURRENT_USER/test' because it does not exist.
At line:1 char:1
+ Get-Item 'registry::HKEY_CURRENT_USER/test'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKEY_CURRENT_USER/test:String) [Get-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
Set-ItemProperty : Cannot find path 'HKEY_CURRENT_USER/test' because it does not exist.
At line:1 char:1
+ Set-ItemProperty 'registry::HKEY_CURRENT_USER/test' -Name test2 -Valu ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKEY_CURRENT_USER/test:String) [Set-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetItemPropertyCommand
Copy-Item : Cannot find path 'HKEY_CURRENT_USER/test' because it does not exist.
At line:1 char:1
+ Copy-Item 'registry::HKEY_CURRENT_USER/test' 'registry::HKEY_CURRENT_ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKEY_CURRENT_USER/test:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
> $PSVersionTable
Name Value
---- -----
PSVersion 6.0.0-rc
PSEdition Core
GitCommitId v6.0.0-rc
OS Microsoft Windows 10.0.16299
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
after trying, I found the law.
related cmdlets
New-Item
New-ItemPropert
Get-ChildItem
Get-Item
Get-ItemProperty
Get-ItemPropertyValue
Set-Item
Set-ItemProperty
Clear-Item
Clear-ItemProperty
Remove-Item
Remove-ItemProperty
Rename-Itemre
Rename-ItemProperty
Copy-Item
Copy-ItemProperty
Move-Item
Move-ItemProperty
This bug also exists in Windows PowerShell (no core)
'/' is allowed in registry key names. Can you to try escape '/'?
@iSazonov
I am using \ to avoid this bug.
but I like automatic processing slash in powershell. (like file path)
To be clear: The real bug is that / is supported at all as a path separator with the registry provider (even though the desire to use / and \ interchangeably, as with the filesystem provider, is understandable).
As @iSazonov points out, / is a valid character in a registry key (or value) name; therefore, it cannot function as the path separator, which in the registry provider's case should _only_ be \.
(Unfortunately, the objects returned by Get-PSProvider have no property that indicates a provider's path separator(s).)
Using one of your examples:
That New-Item 'registry::HKEY_CURRENT_USER/test' succeeds and functions the same as New-Item 'registry::HKEY_CURRENT_USER\test' is a manifestation of the _bug_.
@mklement0 I understand.
item name allow use '/' is too bad
馃槀馃槀馃槀
(Unfortunately, the objects returned by Get-PSProvider have no property that indicates a provider's path separator(s).)
That's why I'm more inclined to think that we need to optimize providers and use types instead of strings.
@iSazonov: What do you mean by using types instead of strings?
Providers work with strings and do parsing its on every operation. This results in poor performance and problems like this.
Tracing this, it looks like there has already been some consideration of this in the NavigationProvider base class here.
The comment seems to indicate that unless both back and forwards slashes are used, we want to treat forward slashes as back slashes. That seems a bit strange to me, but looking for input.
Running New-Item 'registry::HKEY_CURRENT_USER\test\/', it turns out that the path that gets to the NavigationProvider is still 'registry::HKEY_CURRENT_USER\\test', since the SessionStateContainer already normalizes the path.
Related #6833 - seems it is really problem.
It seems like the fix for this would be to make providers responsible for path handling and manage their own directory char separators.
So that way a registry provider can recognise / as an ordinary name char and a filesystem provider can recognise it as a path separator. It might also provide some ability to differentiate UNIX filesystems and Windows ones, although that's less clear.
While there's some consideration about ease of use for users, I think that fidelity to the native environment takes priority there.
My concern is that this could constitute a spiritual breaking change in PowerShell, whereby it's no longer "PowerShell handles cross-platform paths" but "providers are responsible for their paths and the filesystem provider treats / and \ equally". There might not be any significant change in user experience, so maybe it's not worth worrying about. But since SessionStateContainer does path normalisation before hitting any providers, I thought it might be worth discussing.
@rjmholt From MSDN on the structure of the registry
Each key has a name consisting of one or more printable characters. Key names are not case sensitive. Key names cannot include the backslash character (), but any other printable character can be used. Value names and data can include the backslash character
So the natural path separator is \ (and it's what reg.exe uses exclusively) like everywhere else in Windows. However, for the convenience of the people coming to PowerShell from a *nix background (and the idea that we'd port to *nix someday), we chose to also allow / in paths and then normalize as appropriate.
Right, with the tricky bit being "as appropriate".
The definite bug above is that reading a registry key behaves inconsistently with creating a registry key with respect to path normalisation.
But the question remains: do we always do the normalisation and possibly hide some native corner cases (and ideally provide a well-documented way to escape paths), or do we only normalise paths when it doesn't collide with the native implementation?
UNIX filenames allow (ASCII) \ and the Windows registry allows / in keys, so a single path-normalisation policy won't fit everywhere. (A brief look at wsman: and cert: suggests they don't have this problem, but worth checking).
Tagging this for committee review so that it can be discussed alongside https://github.com/PowerShell/PowerShell/issues/6833.
@PowerShell/powershell-committee reviewed this and similar to #6833, path normalization should happen within the provider. If the registry provider is inappropriately normalizing the path, that is a bug that should be fixed.
In Registry provider we need
protected virtual string MakePath(string parent, string child)protected string MakePath(string parent, string child, bool childIsLeaf) (from NavigationProviderBase.cs)private string NormalizePath(string path) (from NavigationProviderBase.cs)I am not sure that it is all that we should make to fix the bug.
@SteveL-MSFT Taking in account #10215 (PowerShell crash) please weigh the issue.
@iSazonov since the recursion issue repros with 5.1, this is not a regression. It's also an unlikely user scenario and I haven't seen many reports of this. I would like to have this fixed, but I don't think it changes the priority.