Powershell: New-Item -ItemType SymbolicLink folder cannot be opened

Created on 21 Dec 2016  ·  18Comments  ·  Source: PowerShell/PowerShell

Use the lastest PowerShell to create a symbolic link folder:

New-Item -ItemType Directory .\a
New-Item .\a\t.txt -Value "hello"
New-Item -ItemType SymbolicLink -Name .\d  -Value .\a
# The Mode property is empty in the result of above cmdlet
Get-ItemPropertyValue .\d -Name Mode
# Get-ItemPropertyValue : Exception getting "Mode": "句柄无效。"
# My OS language is Chinese, "句柄无效" means "invalid handler"

The big problem is that the symbolic link d created above can't be opened. When using the system default PowerShell(PowerShell 5.1, My OS is Windows 10 x64) to create a symbolic link folder, it works well. Another question, now use the lastest PowerShell to remove the symbolic link that is created by the system default PowerShell

> Remove-Item .\d -Recurse
# Remove-Item : F:\test\test-powershell\Symlink\d is an NTFS junction point. Use the Force parameter to delete or modify this object.

It says "d is an NTFS junction point", well, d is a symbolic link,isn't it?

> $PSVersionTable
Name                           Value
----                           -----
SerializationVersion           1.1.0.1
BuildVersion                   3.0.0.0
WSManStackVersion              3.0
GitCommitId                    v6.0.0-alpha.14
PSEdition                      Core
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
CLRVersion
PSRemotingProtocolVersion      2.3
PSVersion                      6.0.0-alpha
Area-Cmdlets Issue-Bug Resolution-Fixed

Most helpful comment

@joeyaiello Honestly, I don't know why someone would want to create a file-type symbolic link to a directory. Windows allows the mklink command to do so---in fact it is the default behavior unless the /D option is explicitly given---so presumably someone thought at one time that it would be useful.

Unix doesn't have the notion of a separate directory-type symbolic link, so new enums for DirectorySymbolicLink and FileSymbolicLink would be meaningless for Linux and OS X. The Linux implementation of ln has a -d switch for creating directory _hard_ links, but that's pretty much never actually allowed, even for the superuser. Combining the -d switch with the -s switch (even on an NTFS volume) simply ignores the -d and creates a "normal" sym link. The OS X version of ln does not even offer the option.

All 18 comments

I'm seeing this as well:

New-Item -Path src -ItemType SymbolicLink -value C:\dev\habitat\components\hab

then:

[HAB-STUDIO] C:\hab\studios> cd src
cd : Cannot find path 'src' because it does not exist.
At line:1 char:1
+ cd src
+ ~~~~~~
    + CategoryInfo          : ObjectNotFound: (src:String) [Set-Location], ItemNotFoundE
   xception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationComm
   and

However it works fine on shipping powershell 5.1 on windows 10.

The problem still exists as of alpha17.

What appears to be happening is that in Core the link is mistakenly created as a _file_ symlink rather than a _directory_ symlink.

You can verify this with cmd /c dir /al d, which in PS Core yields something like (note the <SYMLINK>, which should be <SYMLINKD>):

04/06/2017  04:12 PM    <SYMLINK>      d [C:\Users\jdoe\Desktop\pg\a]

whereas in Windows PS it correctly yields something like:

04/06/2017  04:12 PM    <SYMLINKD>      d [C:\Users\jdoe\Desktop\pg\a]

I agree that the error message mentioning a _junction point_ rather than a symbolic link is misleading, but it sounds like this problem may go away on its own once -Force is no longer needed.

Actually, the -Force issue is not related to this. I was just writing up my own version of this issue when I saw this conversation.

In Windows PS 5.1, New-Item -ItemType SymbolicLink would create a directory symbolic link (<SYMLINKD>) when the target was a directory, a file symbolic link (<SYMLINK>) when the target was a file, and throw an ObjectNotFound error if the target did not exist.

It appears that at some point the cmdlet was changed to bring it more in line with the Windows mklink and Unix ln commands, allowing a symbolic link to be created that linked to a non-existent item. In making that change, the ability to create directory symbolic links to existing directories was (presumably) inadvertently lost.

Since I'm working in this area anyway, and because this is impacting my ability to write tests for #1930, I'm happy to take this on.

I think, though, that there should be some conversation around whether (and how) a user should be able to deliberately create a "file" symbolic link to a directory with New-Item. mklink allows it, and in Unix they're all file links anyway.

@jeffbi:

The -Force issue is entirely incidental to the issue at hand - it was an aside by @yanxyz that perhaps should have been filed as a separate issue to begin with: it relates to _removing_ a directory symlink, whereas the issue at hand is the inability to even _create_ such a symlink. (And, as I said, if -Force will no longer be required to remove a directory symlink, no one will get to see that confusing error message anyway.)

It appears that at some point the cmdlet was changed to bring it more in line with the Windows mklink and Unix ln commands, allowing a symbolic link to be created that linked to a non-existent item. In making that change, the ability to create directory symbolic links to existing directories was (presumably) inadvertently lost.

That sounds like a promising lead: see this commit (@andschwa).

there should be some conversation around whether (and how) a user should be able to deliberately create a "file" symbolic link to a directory with New-Item

Excellent point: If you're creating a symlink to a non-existing item, in the absence of knowing that not-yet-extant item's _type_, on _Windows_ you must specify whether it is a _file_ or _directory_ - and there's currently no way to specify that.

@mklement0 Apologies, I misread your comment.

As for creating a symlink on Windows, I think you really need to be able to specify _file_ or _directory_ whether the target item exists or not. Windows is perfectly happy to allow you to create both a _file_ and a _directory_ symlink to either a file, a directory, or a yet-to-be-created object.

03/24/2017  04:06 PM                 0 test.txt
04/06/2017  10:38 PM    <DIR>          sub
04/06/2017  10:38 PM    <SYMLINK>      sym-to-nix [nix]
04/06/2017  10:38 PM    <SYMLINK>      sym-to-sub [sub]
04/06/2017  10:39 PM    <SYMLINK>      sym-to-text [text.txt]
04/06/2017  10:38 PM    <SYMLINKD>     symd-to-nix [nix]
04/06/2017  10:38 PM    <SYMLINKD>     symd-to-sub [sub]
04/06/2017  10:39 PM    <SYMLINKD>     symd-to-text [text.txt]

@jeffbi Do you work on fix for the Issue?

@iSazonov Since it's getting in my way, I'm about to start.

My intention at the moment is to have the cmdlet create _file_ symlinks to targets that do not exist, and either _file_ or _directory_ symlinks to appropriate existing targets. I still believe we need the ability to have the user specify what kind of link is actually desired. This is only for Windows, as Unix uses _file_ links even to directories.

Ugh, so we can either:

  • add more enums to -Type (i.e. DirectorySymbolicLink and FileSymbolicLink), but that means we have to leave SymbolicLink and have it try to "do the right thing" (file link for files and non-existent targets, and directory link for directories)
  • add a parameter like -SymbolicLinkType, but now you're stuck in the dynamic parameter catch-22

I understand why someone would might want to create a directory symbolic link to a non-existent target, but could someone explain why I might want to create a file-based symbolic link to a directory?

@joeyaiello Honestly, I don't know why someone would want to create a file-type symbolic link to a directory. Windows allows the mklink command to do so---in fact it is the default behavior unless the /D option is explicitly given---so presumably someone thought at one time that it would be useful.

Unix doesn't have the notion of a separate directory-type symbolic link, so new enums for DirectorySymbolicLink and FileSymbolicLink would be meaningless for Linux and OS X. The Linux implementation of ln has a -d switch for creating directory _hard_ links, but that's pretty much never actually allowed, even for the superuser. Combining the -d switch with the -s switch (even on an NTFS volume) simply ignores the -d and creates a "normal" sym link. The OS X version of ln does not even offer the option.

Well, it looks like your PR (#3509) is doing the right thing for now, If people desperately need directory symlinks to non-existent targets, we'll figure it out then.

Sorry, I'm getting ahead of myself a bit. If you want to put this off until more discussion happens, I'm fine with that. I suggested the discussion, you'd think I'd be patient enough to let it happen.

In the Pester tests for #1930 (PR #3441), I'd rather not have to shell out the mklink and ln commands for testing with links, so I'll hold off on completing that PR until a decision is made on this one.

@jeffbi I see that you have already done a full analysis 👍 and we can continue to work on your PR.
It would be great to do a "full specification" or "full description" of the behaivor and place it in description of the PR.
I also want to add that we would be good to do warnings in unusual cases (non-exist targets, file to directory links).

@iSazonov I've updated the PR's description with additional details about how links are created.

As for warnings about "unusual cases", what's unusual to you and I may not be unusual for others. I can imagine scenarios for creating sym links to yet-be-created items. And keep in mind that file-type sym links to directories is the default behavior of mklink when not explicitly given the /D switch.

@jeffbi Thanks for clarify! I thought more about typos in the console when the user can quietly get a dead link 😕

@jeffbi Is Remove-Item on a symbolic directory also resolved via #3509? If not, is it tracked by another issue?

No, the Remove-item issue is not resolved by #3509. I have a separate set of fixes for #621. What #3509 gives me is, like #3441, the ability to use the fixed New-Item in tests for symlinks.

@jeffbi Got it. Thank you for fixing this issue!

👍

Was this page helpful?
0 / 5 - 0 ratings