2015-12-30 23 views
5

Jestem nowy w języku C#. Mam pole tekstowe, w którym wpisuję plik do wyszukania i przycisk "szukaj". w zegar wyszukiwania chcę, aby wypełnić pliki w folderze, ale pojawia się powyższy błąd. Poniżej znajduje się mój kod:

string[] directories = Directory.GetDirectories(@"d:\", 
               "*", 
               SearchOption.AllDirectories); 
string file = textBox1.Text; 
DataGrid dg = new DataGrid(); 

{ 
    var files = new List<string>(); 
    foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady)) 
     { 
     try 
     { 
      files.AddRange(Directory.GetFiles(d.RootDirectory.FullName, file , SearchOption.AllDirectories)); 
     } 
     catch(Exception ex) 
     { 
      MessageBox.Show("the exception is " + ex.ToString()); 
      //Logger.Log(e.Message); // Log it and move on 
     } 
} 

Proszę mi pomóc rozwiązać ten problem. Dzięki

+0

To oczywiste, że nie powinieneś wchodzić w tę TRASĘ. – Hemal

+0

po prostu przeszukując *** wszystkie katalogi w katalogu d: *** doprowadzi do ** wielu ** folderów systemowych, do których normalne konta użytkowników nie powinny mieć dostępu, a dostaniesz taki dostęp odmówiono. – Claies

+0

Nie mam kosza na dysku. Właśnie szukam folderu lub pliku. Rozumiem, że nie powinniśmy iść do kosza. Daj mi znać, jak przynajmniej staram się unikać wyszukiwania w koszu. –

Odpowiedz

2

Najważniejsza zasada podczas wyszukiwania w folderze, który potencjalnie zawiera niedostępnych podfolder jest:

Czy NIE korzystanie SearchOption.AllDirectories!

Zastosowanie SearchOption.TopDirectoryOnly zamiast połączeniu z rekurencyjnego wyszukiwania dla wszystkich dostępnych katalogów.

Korzystanie z naruszenia dostępu spowoduje przerwanie całej pętli nawet przed przetworzeniem pliku/katalogu. Ale jeśli używasz SearchOption.TopDirectoryOnly, pomijasz tylko to, co jest niedostępne.

Istnieje trudniejszy sposób użycia Directory.GetAccessControl() na sprawdzenie katalogu podrzędnego, aby sprawdzić, czy masz dostęp do katalogu przed rozdaniem (ta opcja jest raczej trudna - nie polecam tego, chyba że wiesz dokładnie, jak to zrobić system działa).

Dla rekurencyjnego wyszukiwania, mam ten kod realizowane na własny użytek:

public static List<string> GetAllAccessibleDirectories(string path, string searchPattern) { 
    List<string> dirPathList = new List<string>(); 
    try { 
     List<string> childDirPathList = Directory.GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly).ToList(); //use TopDirectoryOnly 
     if (childDirPathList == null || childDirPathList.Count <= 0) //this directory has no child 
      return null; 
     foreach (string childDirPath in childDirPathList) { //foreach child directory, do recursive search 
      dirPathList.Add(childDirPath); //add the path 
      List<string> grandChildDirPath = GetAllAccessibleDirectories(childDirPath, searchPattern); 
      if (grandChildDirPath != null && grandChildDirPath.Count > 0) //this child directory has children and nothing has gone wrong 
       dirPathList.AddRange(grandChildDirPath.ToArray()); //add the grandchildren to the list 
     } 
     return dirPathList; //return the whole list found at this level 
    } catch { 
     return null; //something has gone wrong, return null 
    } 
} 

ten sposób można nazwać

List<string> accessibleDirs = GetAllAccessibleDirectories(myrootpath, "*"); 

Potem trzeba tylko poszukać/dodać pliki między wszystkie katalogi dostępne.

Uwaga: to pytanie jest dość ciekawe: klasyczna. Sądzę, że istnieją również inne lepsze rozwiązania.

A w przypadku istnieją pewne katalogi które szczególnie chcą uniknąć po odebraniu wszystkich dostępnych katalogów, można również filtrować wyniki List przez LINQ wykorzystując część nazwy podkatalogu jako słowa kluczowego (tj Recycle.Bins).

1

Jak określił Ian w swoim post, nie używaj listy plików rekurencyjnych (Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories)) w przypadku takim jak twój, ponieważ pierwszy wyjątek przerwie dalsze przetwarzanie.

Ponadto, aby nieco złagodzić takie problemy i ogólnie uzyskać lepsze wyniki, należy uruchomić ten program jako Administrator. Można to zrobić, klikając prawym przyciskiem myszy aplikację w Eksploratorze Windows, a następnie zaznaczając opcję Run this program as an administrator na karcie Compatibility.

Powinieneś także użyć kodu jak poniżej do wyszukiwania, więc pośrednie wyjątki nie zatrzymują dalszego szukania.

static void Main(string[] args) { 
    string fileToFind = "*.jpg"; 
    var files = new List<string>(); 

    foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady)) 
     files.AddRange(FindDirectory(fileToFind, d.RootDirectory.FullName)); 
} 

/// <summary> 
/// This function returns the full file path of the matches it finds. 
/// 1. It does not do any parameter validation 
/// 2. It searches recursively 
/// 3. It eats up any error that occurs when requesting files and directories within the specified path 
/// 4. Supports specifying wildcards in the fileToFind parameter. 
/// </summary> 
/// <param name="fileToFind">Name of the file to search, without the path</param> 
/// <param name="path">The path under which the file needs to be searched</param> 
/// <returns>Enumeration of all valid full file paths matching the file</returns> 
public static IEnumerable<string> FindDirectory(string fileToFind, string path) { 

    // Check if "path" directly contains "fileToFind" 
    string[] files = null; 
    try { 
     files = Directory.GetFiles(path, fileToFind); 
    } catch { } 

    if (files != null) { 
     foreach (var file in files) 
      yield return file; 
    } 


    // Check all sub-directories of "path" to see if they contain "fileToFInd" 
    string[] subDirs = null; 
    try { 
     subDirs = Directory.GetDirectories(path); 
    } catch { } 

    if (subDirs == null) 
     yield break; 

    foreach (var subDir in subDirs) 
     foreach (var foundFile in FindDirectory(fileToFind, subDir)) 
      yield return foundFile; 
} 
Powiązane problemy