2013-08-30 63 views
2
public void newestFile(string path) 
{ 
    try 
    { 
     foreach (var item in dir.GetDirectories("*.*", SearchOption.AllDirectories)) 
     { 
      var file = item.GetFiles().OrderByDescending(f => f.LastWriteTime).First(); 
     } 
    } 
    catch (Exception ex) 
    { 

    }      
} 

我想從特定路徑的每個目錄中獲取最新文件,並在捕獲權限異常後繼續,目前我的代碼卡在catch中而不繼續。獲取所有目錄和捕獲權限異常並繼續

+1

Nitpick:你只應該忽略你想忽略的* specific *異常,例如,在你的情況下是'UnauthorizedAccessException'。否則,您可能會意外吞下其他異常,從而創建難以發現的錯誤。 – Heinzi

+0

仍然訪問被拒絕 – user2214609

+2

只搜索頂層目錄並執行你自己的遞歸循環 – Sayse

回答

0
public string[] newestFile(string path){  
    IEnumerable<string> files = new string[]{}; 
    foreach (var item in dir.GetDirectories(Path.Combine(path,"*.*"), SearchOption.AllDirectories)) 
    { 
     try { 
     files = files.Concat(item.GetFiles().OrderByDescending(f => f.LastWriteTime).First()); 
     } 
     catch {} 
    } 
    return files.ToArray(); 
} 
4

不幸的是微軟的落實GetDirectories()極差,而不會處理有關的訪問權限IO異常。

如果你想只跳過那些你沒有訪問(如特殊Recycle Bin文件夾,例如)目錄,那麼你必須寫自己的包裝的Windows API函數FindFirstFile()FindNextFile()

下面是一個完整的例子。如果您運行它,您會看到它列出了您的C:驅動器上可訪問的目錄的所有全部

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Security.Permissions; 
using Microsoft.Win32.SafeHandles; 

namespace Demo 
{ 
    public class Program 
    { 
     private void run() 
     { 
      string root = "C:\\"; 

      foreach (var folder in FolderEnumerator.EnumerateFoldersRecursively(root)) 
       Console.WriteLine(folder); 
     } 

     private static void Main() 
     { 
      new Program().run(); 
     } 
    } 

    public static class FolderEnumerator 
    { 
     public static IEnumerable<string> EnumerateFoldersRecursively(string root) 
     { 
      foreach (var folder in EnumerateFolders(root)) 
      { 
       yield return folder; 

       foreach (var subfolder in EnumerateFoldersRecursively(folder)) 
        yield return subfolder; 
      } 
     } 

     public static IEnumerable<string> EnumerateFolders(string root) 
     { 
      WIN32_FIND_DATA findData; 
      string spec = Path.Combine(root, "*"); 

      using (SafeFindHandle findHandle = FindFirstFile(spec, out findData)) 
      { 
       if (!findHandle.IsInvalid) 
       { 
        do 
        { 
         if ((findData.cFileName != ".") && (findData.cFileName != "..")) // Ignore special "." and ".." folders. 
         { 
          if ((findData.dwFileAttributes & FileAttributes.Directory) != 0) 
          { 
           yield return Path.Combine(root, findData.cFileName); 
          } 
         } 
        } 
        while (FindNextFile(findHandle, out findData)); 
       } 
      } 
     } 

     internal sealed class SafeFindHandle: SafeHandleZeroOrMinusOneIsInvalid 
     { 
      [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] 

      public SafeFindHandle(): base(true) 
      { 
      } 

      protected override bool ReleaseHandle() 
      { 
       if (!IsInvalid && !IsClosed) 
       { 
        return FindClose(this); 
       } 

       return (IsInvalid || IsClosed); 
      } 

      protected override void Dispose(bool disposing) 
      { 
       if (!IsInvalid && !IsClosed) 
       { 
        FindClose(this); 
       } 

       base.Dispose(disposing); 
      } 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     internal struct FILETIME 
     { 
      public uint dwLowDateTime; 
      public uint dwHighDateTime; 

      public long ToLong() 
      { 
       return dwLowDateTime + ((long)dwHighDateTime) << 32; 
      } 
     }; 

     [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 

     internal struct WIN32_FIND_DATA 
     { 
      public FileAttributes dwFileAttributes; 
      public FILETIME  ftCreationTime; 
      public FILETIME  ftLastAccessTime; 
      public FILETIME  ftLastWriteTime; 
      public int   nFileSizeHigh; 
      public int   nFileSizeLow; 
      public int   dwReserved0; 
      public int   dwReserved1; 

      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)] 
      public string cFileName; 

      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)] 
      public string cAlternate; 
     } 

     [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] 
     private static extern SafeFindHandle FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData); 

     [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool FindNextFile(SafeHandle hFindFile, out WIN32_FIND_DATA lpFindFileData); 

     [DllImport("kernel32.dll", SetLastError=true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool FindClose(SafeHandle hFindFile); 

     private const int MAX_PATH = 260; 
     private const int MAX_ALTERNATE = 14; 
    } 
} 

注:此代碼使用FindFirstFile()FindNextFile()它通過的所有文件夾和文件進行迭代。上面的代碼只是忽略文件,只返回文件夾。

使用FindFirstFileEx()並指定一個標誌只返回目錄會更有效率。我把這個改變留給讀者來說是衆所周知的。 ;)

+0

我需要改變在這個類中爲了只接收有權限的目錄? – user2214609

+0

@ user2214609它已經只給你有權限閱讀的目錄。 'if(!findHandle.IsInvalid)'這一行可以防止無效的行。 –

+0

那麼爲什麼它從C返回的所有目錄包括回收站? – user2214609