locked
IO.Directory.Delete - Read-only "Access Denied" RRS feed

  • Question

  • I'm in the middle of a major project converting a VB6 application to .NET and have a requirement to delete a folder and its contents, in this case a complete user profile folder from C:\Documents and Settings.

    In VB6 I used the Scripting.FileSystemObject's DeleteFolder method successfully, however I'm unable to do so in .NET.

    I'm using the following function:

    Public Function DeleteFolder(ByVal strFolderName As String) As Boolean
       Try
           IO.Directory.Delete(strFolderName, True)
           Return True
       Catch ex As Exception
           Debug.Print(ex.Message)
           Return False
       End Try
    End Function

    Whenever I run this, I get an IOException "Access to the path '\\COMPUTERNAME\C$\Documents and Settings\USERNAME\Application Data\Microsoft\Internet Explorer\Quick Launch' is denied."

    As usual, a (probably) very simple problem that's caused me several lost hours.

    Is there a way to get this working, or can someone help me with a replacement routine that will recursively delete the folder's contents, taking care of permissions and read-only issues on-the-fly?

    Thanks!
    Tuesday, March 20, 2007 4:18 AM

Answers

  • Note: Expection handling missing 

    public
    static bool DeleteDirectory(string Path)
    {
          if (Directory.Exists(Path))
          {
            try{
                 ClearAttributes(Path);
                 Directory.Delete(Path, true);
                }
           catch (IOException e){
                Console.WriteLine(e.Message);
                return false;
                }
         }
         return true;
    }

     

    public static void ClearAttributes(string currentDir)
    {
       if (Directory.Exists(currentDir))
       {
           string[] subDirs = Directory.GetDirectories(currentDir);
           foreach(string dir in subDirs)
           ClearAttributes(dir);
           string[] files = files = Directory.GetFiles(currentDir);
           foreach (string file in files)
           File.SetAttributes(file, FileAttributes.Normal);
       }
    }

    Tuesday, May 12, 2009 11:49 PM
  • You try to run the app as a administrator. The directory and any file in it could not be locked, readonly and being using by other app.

     

    Tuesday, March 27, 2007 9:48 AM
  • FYI: I ran into this issue too. The reason is that application data is a hidden folder. If you try to browse through all files and set them to a normal attribute as others has explained above it works for all but hidden and system. Same thing for directories.

    You have to somehow include hidden and system directories (and files) in your collection that you loop through. Im not sure how to do it myself but I would really like to know.

    Thanks all!
    • Proposed as answer by raza.mirza Tuesday, May 12, 2009 11:05 PM
    • Marked as answer by Martin Xie - MSFT Wednesday, May 13, 2009 7:11 AM
    Thursday, July 3, 2008 1:34 PM

All replies

  • You are accessing the folder remotely through the default C: drive share name ("C$").  I'm fairly sure you don't have any rights whatsoever when you use that share.  Does this work with the same path in VB6?
    Tuesday, March 20, 2007 5:40 AM
  • That's not the issue, it works fine with VB6. Also works if I manually map to C$ and delete the folder through explorer, it's only the IO.directory.delete method that fails.

    Note that manually mapping to the drive and deleting the folder isn't an option for the application's target users.

    Also worth noting is that the function IO.Directory.Move, performed on the exact same folder to rename rather than delete a user's profile folder works (also using the C$ share).

    Tuesday, March 20, 2007 6:26 AM
  • You try to run the app as a administrator. The directory and any file in it could not be locked, readonly and being using by other app.

     

    Tuesday, March 27, 2007 9:48 AM
  • I was actually running the app as administrator, and as I said manually doing the same thing works perfectly, so there's no apparent permissions issues, locked or in use files etc.

     

    In the end I wrote my own recursive delete directory function which works flawlessly on the same folders.

     

    I still don't know WHY IO.Directory.Delete failed, but I'm coming to the conclusion that it just isn't very good.

     

    Thursday, April 5, 2007 9:35 AM
  • It seems that Directory.Delete is not able to delete a directory and its contents. It does work like the rd shell command which does not remove folders with content in it.

     

    Did you try the overloaded function Directory.Delete(Path,true) which should be able to recursive delete do this?

     

    Yours,

        Alois Kraus

     

    Thursday, April 5, 2007 11:36 AM
  • I did indeed try that, and it didn't work.

     

    That is to say, it worked in many cases, but failed when deleting a profile folder, even though I was able to delete the same folder through Explorer and via my own function (that I ended up making to do what Directory.Delete supposedly should do).

     

    Seems to me there's something specifically tricky about profile folders that confuses Directory.Delete, but the only feedback I get is "access denied", which doesn't help me.

     

    Never mind.

    Thursday, April 5, 2007 12:30 PM
  • I cannot repro the problem in the VB.NET 2005. No matter that I specify local path or UNC path as well as different folder location, as long as the directory exists and can be writen and not being used, it always can be deleted successfully.

    Public Class Form1

     

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

            'System.IO.Directory.Delete("\\Martin\\c$\\Documents and Settings\\111", True)

            ' Call DeleteFolder("C:\\Documents and Settings\\111")

            ' Call DeleteFolder("\\Martin\\c$\\Documents and Settings\\111")

            ' Call DeleteFolder("C:\\Documents and Settings\\v-maxie\\My Documents\\111")

            Call DeleteFolder("\\Martin\\c$\\Documents and Settings\\v-maxie\\My Documents\\111")

     

        End Sub

     

        Public Function DeleteFolder(ByVal strFolderName As String) As Boolean

            Try

                IO.Directory.Delete(strFolderName, True)

                Return True

            Catch ex As Exception

                Debug.Print(ex.Message)

                Return False

            End Try

        End Function

     

    End Class

     

    I introduce you about the “Process Monitor” tool to check further. 

    The tool is an advanced monitoring tool for Windows that shows real-time file system, Registry and process/thread activity.

    It is a very useful utility for troubleshooting.

    http://www.microsoft.com/technet/sysinternals/processesandthreads/processmonitor.mspx

    Friday, April 6, 2007 6:51 AM
  • Hi

    I have the same issue with C#.NET2.0....

    Did you find the source of this?

    I have all the permissions and ownership on folder (It is a "Roaming profile" folder), I can move it, I can delete manually....

    I get the same exception.

    This is a very frustrating issue...

    Can you help me with this please?

    Monday, May 14, 2007 8:02 AM
  • Hi

    I am facing the same issue.

    However I have found out what causes the error.

    When you delete a directory that is "read only" you will get the above error.

    This is not a problem when deleting an empty directory as it would be fairly easy to determine if the attribute is set, but when you use the overloaded method, that deletes subdirectories it becomes far more tricky as the method stops is it encounters a "read only" Directory in the structure it deletes.

     

    Profiles always contains folders wich are "read only" and because of this the delete method will always fail.

     

    Does anyone know of a method to remove the read only flag on alle subdirectories?

     

    Best regards

    Daniel

    • Proposed as answer by Sea Lau Thursday, November 8, 2012 9:14 AM
    Wednesday, May 16, 2007 7:55 AM
  • You could just change the attributes of the hidden, system and read-only files:

          System.IO.File.SetAttributes(path, System.IO.FileAttributes.Normal);
    Wednesday, May 16, 2007 11:51 AM
  • FYI: I ran into this issue too. The reason is that application data is a hidden folder. If you try to browse through all files and set them to a normal attribute as others has explained above it works for all but hidden and system. Same thing for directories.

    You have to somehow include hidden and system directories (and files) in your collection that you loop through. Im not sure how to do it myself but I would really like to know.

    Thanks all!
    • Proposed as answer by raza.mirza Tuesday, May 12, 2009 11:05 PM
    • Marked as answer by Martin Xie - MSFT Wednesday, May 13, 2009 7:11 AM
    Thursday, July 3, 2008 1:34 PM
  • Note: Expection handling missing 

    public
    static bool DeleteDirectory(string Path)
    {
          if (Directory.Exists(Path))
          {
            try{
                 ClearAttributes(Path);
                 Directory.Delete(Path, true);
                }
           catch (IOException e){
                Console.WriteLine(e.Message);
                return false;
                }
         }
         return true;
    }

     

    public static void ClearAttributes(string currentDir)
    {
       if (Directory.Exists(currentDir))
       {
           string[] subDirs = Directory.GetDirectories(currentDir);
           foreach(string dir in subDirs)
           ClearAttributes(dir);
           string[] files = files = Directory.GetFiles(currentDir);
           foreach (string file in files)
           File.SetAttributes(file, FileAttributes.Normal);
       }
    }

    Tuesday, May 12, 2009 11:49 PM
  • I had the same problem as everyone else and that second function worked for me.

    public static void ClearAttributes( string currentDir)
    {
       if ( Directory .Exists(currentDir))
       {
           string [] subDirs = Directory .GetDirectories(currentDir);
           foreach ( string dir in subDirs)
           ClearAttributes(dir);
           string [] files = files = Directory .GetFiles(currentDir);
           foreach ( string file in files)
           File .SetAttributes(file, FileAttributes .Normal);
       }
    }

    Thursday, May 21, 2009 7:26 PM
  • I have the same issue and set FileAttributes to Normal didn't work.

     

    Thursday, July 1, 2010 9:27 AM
  • Directory attributes must be set to normal too.
    • Proposed as answer by Brian.k Friday, July 2, 2010 5:15 AM
    Friday, July 2, 2010 5:14 AM
  • Just as a helpful note as I had to bang my head against this. Failed to delete due to hidden/readonly directory. I would say that the dot net library isn't brilliant in this job.

    Set the attributes for the directory to normal as per previous post:

    System.IO.File.SetAttributes(DirectoryPath, System.IO.FileAttributes.Normal);

    Directory

     

    .Delete(DirectoryPath, true);

    • Proposed as answer by ShawnCurranGlasgow Monday, February 27, 2012 2:53 PM
    • Unproposed as answer by ShawnCurranGlasgow Monday, February 27, 2012 2:53 PM
    • Proposed as answer by Sea Lau Thursday, November 8, 2012 9:15 AM
    Monday, January 17, 2011 1:43 PM
  •    

    Had the same problem deleting user profiles and created the below sub to get round it!

    Private Sub deleteWindowsDirectory(ByVal path As String) Try Dim t = My.Computer.FileSystem.GetDirectories(path, FileIO.SearchOption.SearchAllSubDirectories) 'iterate through the files of the top level path Dim a = My.Computer.FileSystem.GetFiles(path) For c As Integer = 0 To a.Count - 1 Dim p = My.Computer.FileSystem.GetFileInfo(a.Item(c)) p.Attributes = IO.FileAttributes.Normal Next 'iterate through sub dirs and and files in the sub dirs. For i As Integer = 0 To t.Count - 1 Dim r = My.Computer.FileSystem.GetDirectoryInfo(t.Item(i)) r.Attributes = IO.FileAttributes.Normal Dim g = My.Computer.FileSystem.GetFiles(t.Item(i)) For c As Integer = 0 To g.Count - 1 Dim p = My.Computer.FileSystem.GetFileInfo(g.Item(c)) p.Attributes = IO.FileAttributes.Normal Next Next My.Computer.FileSystem.DeleteDirectory(path, FileIO.DeleteDirectoryOption.DeleteAllContents) Catch ex As Exception MsgBox(ex.Message) End Try End Sub


    Monday, February 27, 2012 3:04 PM
  • The following code is a fix to the C# code posted above by Raza. This will recursively look through each folder from the top down, marking files and folders as normal.

    I tested this on a .V2 roaming profile folder.

            private void ClearAttributes(string strDest)
            {
                if (Directory.Exists(strDest))
                {
                    DirectoryInfo diFolder = new DirectoryInfo(strDest);
                    diFolder.Attributes = FileAttributes.Normal;
                    string[] files = files = Directory.GetFiles(strDest);
                    foreach (string file in files)
                    {
                        File.SetAttributes(file, FileAttributes.Normal);
                    }
                    string[] subDirs = Directory.GetDirectories(strDest);
    
                    foreach (string dir in subDirs)
                    {
                        ClearAttributes(dir);
                    }
                }
            }


    • Edited by Nathan McKaskle Wednesday, February 5, 2014 9:33 PM
    • Proposed as answer by Daniel_CH Thursday, July 30, 2020 4:30 PM
    Wednesday, February 5, 2014 9:32 PM
  • Thanks! Did now work with your code ;-)
    Thursday, July 30, 2020 4:31 PM