locked
Directory.getfiles gives me access denied RRS feed

  • Question

  • Hi Everyone,

      I want to get the list of files in a given location.So i'm using Directory.getfiles in C#  -  When i had given "E:\" which contains "system volume information folder" it is throwing me access denied exception. So is there any way such that if there are any access issues then i can leave it and continue the same process.. or Any other solution available to get the list of files in a given location.My concern is if in command prompt "E:\>dir" command leaves the "system volume information folder" and gives me the list of files why can't i do the same in C#..

    Any help in this regard, appreciated.

    Thanks in advance

    Venkata Ramesh V

     

    Wednesday, August 3, 2011 3:03 PM

Answers

  • If you want to continue getting files after the error occurens, then you can use a Stack<T> class.

    Example:

     

      public static IEnumerable<string> GetFiles(string root, string searchPattern)
      {
        Stack<string> pending = new Stack<string>();
        pending.Push(root);
        while (pending.Count != 0)
        {
          var path = pending.Pop();
          string[] next = null;
          try
          {
            next = Directory.GetFiles(path, searchPattern);          
          }
          catch { }
          if(next != null && next.Length != 0)
            foreach (var file in next) yield return file;
          try
          {
            next = Directory.GetDirectories(path);
            foreach (var subdir in next) pending.Push(subdir);
          }
          catch { }
        }
      }
    


     


    Mitja
    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 4:53 PM
  • The System Volume Information folder is a hidden system folder that stores system restore points. In general, messing with it is a bad idea - that's why it is hidden by default. I believe you also have to be logged in as an administrator to be able to view the contents.

    The better option is to keep it secured, and just skip the directory if you don't have access to it. To do that, you can just use a Try/Catch block:

    try
    {
        string[] fileNames = Directory.GetFiles(sDir);
        // Do whatever you want with fileNames
    }
    catch (UnauthorizedAccessException)
    {
        // Code here will be hit if access is denied. You can also
        // leave this empty to ignore the error.
    }
    



    Check out My Blog for tech news, development tips, and other information for geeks like me.
    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 3:38 PM
  • Or you can use a simple foreach loop, which will continue getting files (even if there will an Exception (if needed) pop up):

    foreach(string filePath in Directory.GetFiles(blah))
    {
      try
      {
       //do something with file
      }
      catch(UnauthorizedAccessException ex)
      {
       //create an exception if needed (you can create a messageBox, or nothing)!
      }
    }
    



    Mitja
    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 4:55 PM
  • Here's a solution that uses Win32 calls to traverse the files.  Instead of giving you a global exception, it will return a different code for files that are inaccessible -- you can then get the rest of the files you need. This isn't perfect yet -- specifically for your circumstances, this line:

     if (data.dwFileAttributes == 16)
    

    will need some thoughts.  It checks the file type -- and unfortunately there doesn't seem to be an easy attribute to use, but here's an incomplete list: http://msdn.microsoft.com/en-us/library/gg258117%28v=vs.85%29.aspx.  But anyways, this line is asking if it the current entry is a folder.  In your case, this attribute will be something funky, and the code will simply think it's a file.  You can then use the File.Exists method on the resulting list to filter them out (or modify the source to ignore them).

     

    Usage of the class is easy:

    foreach (String file in new EnumerateDirectory.EnumerateDirectory(@"X:", true))
    {
     //file is the full path to the file
    }
    

    Here's the complete source.  Oh, and as a fringe benefit, this is considerably faster, and it doesn't block your code until every file is found -- it returns after it finds the next file as a file enumerator should:

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace EnumerateDirectory
    {
      public class EnumerateDirectory : IEnumerable<String>, IEnumerator<string>
      {
        [Serializable,
        System.Runtime.InteropServices.StructLayout
        (System.Runtime.InteropServices.LayoutKind.Sequential,
        CharSet = System.Runtime.InteropServices.CharSet.Auto
        ),
        System.Runtime.InteropServices.BestFitMapping(false)]
        private struct WIN32_FIND_DATA
        {
          public int dwFileAttributes;
          public int ftCreationTime_dwLowDateTime;
          public int ftCreationTime_dwHighDateTime;
          public int ftLastAccessTime_dwLowDateTime;
          public int ftLastAccessTime_dwHighDateTime;
          public int ftLastWriteTime_dwLowDateTime;
          public int ftLastWriteTime_dwHighDateTime;
          public int nFileSizeHigh;
          public int nFileSizeLow;
          public int dwReserved0;
          public int dwReserved1;
          [System.Runtime.InteropServices.MarshalAs
          (System.Runtime.InteropServices.UnmanagedType.ByValTStr,
          SizeConst = 260)]
          public string cFileName;
          [System.Runtime.InteropServices.MarshalAs
          (System.Runtime.InteropServices.UnmanagedType.ByValTStr,
          SizeConst = 14)]
          public string cAlternateFileName;
        }
        [System.Runtime.InteropServices.DllImport
        ("kernel32.dll",
        CharSet = System.Runtime.InteropServices.CharSet.Auto,
        SetLastError = true)]
        private static extern IntPtr FindFirstFile(string pFileName,
          ref WIN32_FIND_DATA pFindFileData);
        [System.Runtime.InteropServices.DllImport
        ("kernel32.dll",
        CharSet = System.Runtime.InteropServices.CharSet.Auto,
        SetLastError = true)]
        private static extern bool FindNextFile(IntPtr hndFindFile,
          ref WIN32_FIND_DATA lpFindFileData);
        [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool FindClose(IntPtr hndFindFile);
        private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
    
        public class FILETIME
        {
          public long dwLowDateTime;
          public long dwHighDateTime;
        }
    
        public class SYSTEMTIME
        {
          public int wYear;
          public int wMonth;
          public int wDayOfWeek;
          public int wDay;
          public int wHour;
          public int wMinute;
          public int wSecond;
          public int wMilliseconds;
        }
    
        Stack<SearchHandle> handles = new Stack<SearchHandle>();
        String dir;
        bool sub;
    
        public EnumerateDirectory(String directory)
        {
          init(directory, false);
        }
    
        public EnumerateDirectory(String directory, bool SearchSubdirectories)
        {
          init(directory, SearchSubdirectories);
        }
    
        protected void init(String directory, bool searchsubdirectories)
        {
          if (!Directory.Exists(directory))
            throw new ArgumentException("Directory does not exist.");
          dir = directory;
          sub = searchsubdirectories;
    
        }
    
        public IEnumerator<string> GetEnumerator()
        {
          Reset();
          return this;
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
          Reset();
          return this;
        }
    
        public string Current
        {
          get;
          protected set;
        }
            
        public void Dispose()
        {
          foreach (var handle in handles)
            FindClose(handle.handle);
          handles.Clear();
        }
    
        protected void Pop()
        {
          var handle = handles.Pop();
          FindClose(handle.handle);
        }
    
        object System.Collections.IEnumerator.Current
        {
          get { return Current; }
        }
    
        public bool MoveNext()
        {
          Current = GetNextFile();
          return Current != null;
        }
    
        protected String GetNextFile()
        {
          WIN32_FIND_DATA data = new WIN32_FIND_DATA();
          String res = null;
          if (handles.Count == 0)
            return null;
          FindNextFile(handles.Peek().handle, ref data);
          if (data.dwFileAttributes == 16)
          {
            if (sub)
            {
              var newHandle = getNewHandle(Path.Combine(handles.Peek().dir, data.cFileName));
              handles.Push(newHandle);
              return GetNextFile();
            }
            else
            {
              return GetNextFile();
            }
          }
          else
          {
            if (String.IsNullOrEmpty(data.cFileName))
            {
              if (handles.Count > 0)
              {
                Pop();
                res = GetNextFile();
              }else
                res = null;
            }
            else
              res = Path.Combine(handles.Peek().dir, data.cFileName);
          }
          return res;
        }
    
        public void Reset()
        {
          Dispose();
          handles.Push(getNewHandle(dir));
        }
    
        private SearchHandle getNewHandle(String directory)
        {
          var data = new WIN32_FIND_DATA();
          var handle = FindFirstFile(Path.Combine(directory, "*"), ref data);
          FindNextFile(handle, ref data);
          return new SearchHandle(handle, directory);
        }
    
      }
    
      class SearchHandle
      {
        public IntPtr handle;
        public String dir;
    
        public SearchHandle(IntPtr handle, String dir)
        {
          this.handle = handle;
          this.dir = dir;
        }
      }
    }
    
    


    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 4:56 PM

All replies

  • The System Volume Information folder is a hidden system folder that stores system restore points. In general, messing with it is a bad idea - that's why it is hidden by default. I believe you also have to be logged in as an administrator to be able to view the contents.

    The better option is to keep it secured, and just skip the directory if you don't have access to it. To do that, you can just use a Try/Catch block:

    try
    {
        string[] fileNames = Directory.GetFiles(sDir);
        // Do whatever you want with fileNames
    }
    catch (UnauthorizedAccessException)
    {
        // Code here will be hit if access is denied. You can also
        // leave this empty to ignore the error.
    }
    



    Check out My Blog for tech news, development tips, and other information for geeks like me.
    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 3:38 PM
  • who can access the directory? everyone?

    I think you should use Directory.SetAccessControl before use Directory.GetFiles

    Att.

    Alex

     

    Wednesday, August 3, 2011 3:45 PM
  • Hi

    You cannot give more powers than logged-in user has...Best approach is handle exception and ignore as Tim suggested....


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".
    Wednesday, August 3, 2011 4:28 PM
  • If you want to continue getting files after the error occurens, then you can use a Stack<T> class.

    Example:

     

      public static IEnumerable<string> GetFiles(string root, string searchPattern)
      {
        Stack<string> pending = new Stack<string>();
        pending.Push(root);
        while (pending.Count != 0)
        {
          var path = pending.Pop();
          string[] next = null;
          try
          {
            next = Directory.GetFiles(path, searchPattern);          
          }
          catch { }
          if(next != null && next.Length != 0)
            foreach (var file in next) yield return file;
          try
          {
            next = Directory.GetDirectories(path);
            foreach (var subdir in next) pending.Push(subdir);
          }
          catch { }
        }
      }
    


     


    Mitja
    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 4:53 PM
  • Or you can use a simple foreach loop, which will continue getting files (even if there will an Exception (if needed) pop up):

    foreach(string filePath in Directory.GetFiles(blah))
    {
      try
      {
       //do something with file
      }
      catch(UnauthorizedAccessException ex)
      {
       //create an exception if needed (you can create a messageBox, or nothing)!
      }
    }
    



    Mitja
    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 4:55 PM
  • Here's a solution that uses Win32 calls to traverse the files.  Instead of giving you a global exception, it will return a different code for files that are inaccessible -- you can then get the rest of the files you need. This isn't perfect yet -- specifically for your circumstances, this line:

     if (data.dwFileAttributes == 16)
    

    will need some thoughts.  It checks the file type -- and unfortunately there doesn't seem to be an easy attribute to use, but here's an incomplete list: http://msdn.microsoft.com/en-us/library/gg258117%28v=vs.85%29.aspx.  But anyways, this line is asking if it the current entry is a folder.  In your case, this attribute will be something funky, and the code will simply think it's a file.  You can then use the File.Exists method on the resulting list to filter them out (or modify the source to ignore them).

     

    Usage of the class is easy:

    foreach (String file in new EnumerateDirectory.EnumerateDirectory(@"X:", true))
    {
     //file is the full path to the file
    }
    

    Here's the complete source.  Oh, and as a fringe benefit, this is considerably faster, and it doesn't block your code until every file is found -- it returns after it finds the next file as a file enumerator should:

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace EnumerateDirectory
    {
      public class EnumerateDirectory : IEnumerable<String>, IEnumerator<string>
      {
        [Serializable,
        System.Runtime.InteropServices.StructLayout
        (System.Runtime.InteropServices.LayoutKind.Sequential,
        CharSet = System.Runtime.InteropServices.CharSet.Auto
        ),
        System.Runtime.InteropServices.BestFitMapping(false)]
        private struct WIN32_FIND_DATA
        {
          public int dwFileAttributes;
          public int ftCreationTime_dwLowDateTime;
          public int ftCreationTime_dwHighDateTime;
          public int ftLastAccessTime_dwLowDateTime;
          public int ftLastAccessTime_dwHighDateTime;
          public int ftLastWriteTime_dwLowDateTime;
          public int ftLastWriteTime_dwHighDateTime;
          public int nFileSizeHigh;
          public int nFileSizeLow;
          public int dwReserved0;
          public int dwReserved1;
          [System.Runtime.InteropServices.MarshalAs
          (System.Runtime.InteropServices.UnmanagedType.ByValTStr,
          SizeConst = 260)]
          public string cFileName;
          [System.Runtime.InteropServices.MarshalAs
          (System.Runtime.InteropServices.UnmanagedType.ByValTStr,
          SizeConst = 14)]
          public string cAlternateFileName;
        }
        [System.Runtime.InteropServices.DllImport
        ("kernel32.dll",
        CharSet = System.Runtime.InteropServices.CharSet.Auto,
        SetLastError = true)]
        private static extern IntPtr FindFirstFile(string pFileName,
          ref WIN32_FIND_DATA pFindFileData);
        [System.Runtime.InteropServices.DllImport
        ("kernel32.dll",
        CharSet = System.Runtime.InteropServices.CharSet.Auto,
        SetLastError = true)]
        private static extern bool FindNextFile(IntPtr hndFindFile,
          ref WIN32_FIND_DATA lpFindFileData);
        [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool FindClose(IntPtr hndFindFile);
        private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
    
        public class FILETIME
        {
          public long dwLowDateTime;
          public long dwHighDateTime;
        }
    
        public class SYSTEMTIME
        {
          public int wYear;
          public int wMonth;
          public int wDayOfWeek;
          public int wDay;
          public int wHour;
          public int wMinute;
          public int wSecond;
          public int wMilliseconds;
        }
    
        Stack<SearchHandle> handles = new Stack<SearchHandle>();
        String dir;
        bool sub;
    
        public EnumerateDirectory(String directory)
        {
          init(directory, false);
        }
    
        public EnumerateDirectory(String directory, bool SearchSubdirectories)
        {
          init(directory, SearchSubdirectories);
        }
    
        protected void init(String directory, bool searchsubdirectories)
        {
          if (!Directory.Exists(directory))
            throw new ArgumentException("Directory does not exist.");
          dir = directory;
          sub = searchsubdirectories;
    
        }
    
        public IEnumerator<string> GetEnumerator()
        {
          Reset();
          return this;
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
          Reset();
          return this;
        }
    
        public string Current
        {
          get;
          protected set;
        }
            
        public void Dispose()
        {
          foreach (var handle in handles)
            FindClose(handle.handle);
          handles.Clear();
        }
    
        protected void Pop()
        {
          var handle = handles.Pop();
          FindClose(handle.handle);
        }
    
        object System.Collections.IEnumerator.Current
        {
          get { return Current; }
        }
    
        public bool MoveNext()
        {
          Current = GetNextFile();
          return Current != null;
        }
    
        protected String GetNextFile()
        {
          WIN32_FIND_DATA data = new WIN32_FIND_DATA();
          String res = null;
          if (handles.Count == 0)
            return null;
          FindNextFile(handles.Peek().handle, ref data);
          if (data.dwFileAttributes == 16)
          {
            if (sub)
            {
              var newHandle = getNewHandle(Path.Combine(handles.Peek().dir, data.cFileName));
              handles.Push(newHandle);
              return GetNextFile();
            }
            else
            {
              return GetNextFile();
            }
          }
          else
          {
            if (String.IsNullOrEmpty(data.cFileName))
            {
              if (handles.Count > 0)
              {
                Pop();
                res = GetNextFile();
              }else
                res = null;
            }
            else
              res = Path.Combine(handles.Peek().dir, data.cFileName);
          }
          return res;
        }
    
        public void Reset()
        {
          Dispose();
          handles.Push(getNewHandle(dir));
        }
    
        private SearchHandle getNewHandle(String directory)
        {
          var data = new WIN32_FIND_DATA();
          var handle = FindFirstFile(Path.Combine(directory, "*"), ref data);
          FindNextFile(handle, ref data);
          return new SearchHandle(handle, directory);
        }
    
      }
    
      class SearchHandle
      {
        public IntPtr handle;
        public String dir;
    
        public SearchHandle(IntPtr handle, String dir)
        {
          this.handle = handle;
          this.dir = dir;
        }
      }
    }
    
    


    • Marked as answer by Jackie-Sun Tuesday, August 9, 2011 5:46 AM
    Wednesday, August 3, 2011 4:56 PM