Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2693,13 +2693,22 @@ protected override void ProcessRecord()
bool shouldRecurse = Recurse;
bool treatAsFile = false;

// only check if path is a directory using DirectoryInfo if using FileSystemProvider
// only check if path is a directory using DirectoryInfo if using FileSystemProvider, otherwise will fail for other providers like Registry
if (resolvedPath.Provider.Name.Equals(FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
{
try
{
System.IO.DirectoryInfo di = new(providerPath);
if (di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0)

if (ExperimentalFeature.IsEnabled(ExperimentalFeature.PSForceRemoveReparsePoint))
{
if (di != null && di.Attributes.HasFlag(System.IO.FileAttributes.ReparsePoint) && (di.Attributes.HasFlag(System.IO.FileAttributes.Directory) && !shouldRecurse))
{
shouldRecurse = false;
treatAsFile = true;
}
}
else if (di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0)
{
shouldRecurse = false;
treatAsFile = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class ExperimentalFeature

internal const string EngineSource = "PSEngine";
internal const string PSAnsiProgressFeatureName = "PSAnsiProgress";
internal const string PSForceRemoveReparsePoint = "PSForceRemoveReparsePoint";

#endregion

Expand Down Expand Up @@ -136,6 +137,9 @@ static ExperimentalFeature()
new ExperimentalFeature(
name: PSAnsiProgressFeatureName,
description: "Enable lightweight progress bar that leverages ANSI codes for rendering"),
new ExperimentalFeature(
name: PSForceRemoveReparsePoint,
description: "Enable -Force to remove reparsepoint folders like on OneDrive"),
};
EngineExperimentalFeatures = new ReadOnlyCollection<ExperimentalFeature>(engineFeatures);

Expand Down
18 changes: 12 additions & 6 deletions src/System.Management.Automation/namespaces/FileSystemProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3108,12 +3108,18 @@ private void RemoveDirectoryInfoItem(DirectoryInfo directory, bool recurse, bool
{
try
{
// TODO:
// Different symlinks seem to vary by behavior.
// In particular, OneDrive symlinks won't remove without recurse,
// but the .NET API here does not allow us to distinguish them.
// We may need to revisit using p/Invokes here to get the right behavior
directory.Delete();
if (force && ExperimentalFeature.IsEnabled(ExperimentalFeature.PSForceRemoveReparsePoint))
{
// For non-reparse points, the behavior is to manually recurse so if `-Confirm` is used, then the user
// gets a confirmation at each level. Unfortunately, a reparse point behaves differently and requires
// the `Delete(recursive)` overload to successfully delete the folder (like a OneDrive folder).
// Symlinks are still treated as files.
directory.Delete(recursive: recurse);
}
else
{
directory.Delete();
}
}
catch (Exception e)
{
Expand Down