diff --git a/src/code/Utils.cs b/src/code/Utils.cs index ae540f9e4..7fe491376 100644 --- a/src/code/Utils.cs +++ b/src/code/Utils.cs @@ -1658,6 +1658,16 @@ public static void DeleteDirectoryWithRestore(string dirPath) } } + private static void SetAttributesHelper(DirectoryInfo directory) + { + foreach (var subDirectory in directory.GetDirectories()) + { + subDirectory.Attributes = FileAttributes.Normal; + SetAttributesHelper(subDirectory); + } + + directory.Attributes = FileAttributes.Normal; + } /// /// Deletes a directory and its contents /// This is a workaround for .NET Directory.Delete(), which can fail with WindowsPowerShell @@ -1672,13 +1682,17 @@ public static void DeleteDirectory(string dirPath) } // Remove read only file attributes first - foreach (var dirFilePath in Directory.GetFiles(dirPath,"*",SearchOption.AllDirectories)) + foreach (var dirFilePath in Directory.GetFiles(dirPath, "*", SearchOption.AllDirectories)) { if (File.GetAttributes(dirFilePath).HasFlag(FileAttributes.ReadOnly)) { File.SetAttributes(dirFilePath, File.GetAttributes(dirFilePath) & ~FileAttributes.ReadOnly); } } + + DirectoryInfo rootDir = new DirectoryInfo(dirPath); + SetAttributesHelper(rootDir); + // Delete directory recursive, try multiple times before throwing ( #1662 ) int maxAttempts = 5; int msDelay = 5; @@ -1686,7 +1700,7 @@ public static void DeleteDirectory(string dirPath) { try { - Directory.Delete(dirPath,true); + Directory.Delete(dirPath, true); return; } catch (Exception ex) @@ -1695,6 +1709,17 @@ public static void DeleteDirectory(string dirPath) { Thread.Sleep(msDelay); } + else if (ex is System.IO.IOException) + { + string psVersion = System.Management.Automation.Runspaces.Runspace.DefaultRunspace.Version.ToString(); + if (ex.Message.Contains("The directory is not empty") && psVersion.StartsWith("5")) + { + // there is a known bug with WindowsPowerShell and OneDrive based module paths, where .NET Directory.Delete() will throw a 'The directory is not empty.' error. + throw new Exception(string.Format("Cannot uninstall module with OneDrive based path on WindowsPowerShell due to .NET issue. Try installing and uninstalling using PowerShellCore if using OneDrive."), ex); + } + + throw new Exception(string.Format("Access denied to path while deleting path {0}", dirPath), ex); + } else { throw;