Skip to content

Fix Remove-Item <symbolic link to directory> #621

Closed
@andyleejordan

Description

@andyleejordan

If you make a symbolic link to a directory on Windows (with administrative privileges of course), and then try to delete said link, you get this:

|Y> Yes |A> Yes to All |N> No |L> No to All |S> Suspend [Default is (Y]
PS C:\Users\anschwa\src\PowerShell> remove-item -Force .\foobar\
Confirm
The item at C:\Users\anschwa\src\PowerShell\foobar\ has children and the Recurse parameter was not specified. If you con
tinue, all children will be removed with the item. Are you sure you want to continue?

|Y> Yes |A> Yes to All |N> No |L> No to All |S> Suspend [Default is (Y]
n
PS C:\Users\anschwa\src\PowerShell> remove-item -Force .\foobar\ -Recurse
remove-item : There is a mismatch between the tag specified in the request and the tag present in the reparse point
At line:1 char:1
+ remove-item -Force .\foobar\ -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Remove-Item], Win32Exception
    + FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.RemoveItemCommand

PS C:\Users\anschwa\src\PowerShell> $error[0].Exception.StackTrace
   at Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods.DeleteJunction(String junctionPath) in C:\Users\
anschwa\src\PowerShell\src\monad\monad\src\namespaces\FileSystemProvider.cs:line 8447
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveDirectoryInfoItem(DirectoryInfo directory, Boolean recurse,
 Boolean force, Boolean rootOfRemoval) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\FileSystemProvi
der.cs:line 2859
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveItem(String path, Boolean recurse) in C:\Users\anschwa\src\
PowerShell\src\monad\monad\src\namespaces\FileSystemProvider.cs:line 2733
   at System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem(String path, Boolean recurse, CmdletProvi
derContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\ContainerProviderBase.cs:line 422
   at System.Management.Automation.SessionStateInternal.RemoveItem(CmdletProvider providerInstance, String path, Boolean
 recurse, CmdletProviderContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\engine\SessionStateConta
iner.cs:line 1152

Remove-Item is thinking the link is a directory and so failing to delete it.

If the code is changed such that File.Delete(junction) is used instead of native calls, you get:

PS C:\Users\anschwa\src\PowerShell> rm .\foobar\ -Force
Confirm
The item at C:\Users\anschwa\src\PowerShell\foobar\ has children and the Recurse parameter was not specified. If you con
tinue, all children will be removed with the item. Are you sure you want to continue?

|Y> Yes |A> Yes to All |N> No |L> No to All |S> Suspend [Default is (Y]
y
rm : Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
At line:1 char:1
+ rm .\foobar\ -Force
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Remove-Item], FormatException
    + FullyQualifiedErrorId : System.FormatException,Microsoft.PowerShell.Commands.RemoveItemCommand

PS C:\Users\anschwa\src\PowerShell> $error[0].Exception.StackTrace
   at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.Format(IFormatProvider provider, String format, Object arg0)
   at System.Management.Automation.Internal.StringUtil.Format(String formatSpec, Object o) in C:\Users\anschwa\src\Power
Shell\src\monad\monad\src\utils\StringUtil.cs:line 18
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveDirectoryInfoItem(DirectoryInfo directory, Boolean recurse,
 Boolean force, Boolean rootOfRemoval) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\FileSystemProvi
der.cs:line 2863
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveItem(String path, Boolean recurse) in C:\Users\anschwa\src\
PowerShell\src\monad\monad\src\namespaces\FileSystemProvider.cs:line 2733
   at System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem(String path, Boolean recurse, CmdletProvi
derContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\ContainerProviderBase.cs:line 422
   at System.Management.Automation.SessionStateInternal.RemoveItem(CmdletProvider providerInstance, String path, Boolean
 recurse, CmdletProviderContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\engine\SessionStateConta
iner.cs:line 1152

It fails even sooner (I think because there aren't actually any children to pass delete recursively, so it gets an empty list; just a guess).

If you use Directory.Delete(junctionPath), it works just fine!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Committee-ReviewedPS-Committee has reviewed this and made a decisionIssue-BugIssue has been identified as a bug in the productOS-WindowsResolution-FixedThe issue is fixed.WG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions