2016-01-09 2 views
1

В настоящее время я пишу программу на C#, которая скопирует все файлы профиля пользователя на внешнее устройство (в данном случае на мой домашний сервер).C# File Permissions

Когда мой код выполняет итерацию через мои файлы и папки, он выдает UnauthorizedAccessException.

У меня есть Googled это и искал StackOverflow, но я не могу найти четкое решение, которое не связано с завершением моего процесса. Идея состоит в том, что она должна копировать файлы и папки, имеющие разрешения на чтение.

У меня было это, когда я только начинал, но я легко исправил его, ограничив, какие каталоги я бы сделал резервным (хотя я бы предпочел полную резервную копию).

Вот мой код:

FileInfo f = new FileInfo(_configuration.Destination); 
if (!f.Directory.Exists) 
{ 
    f.Directory.Create(); 
} 

string[] backupDirectories = new string[] 
{ 
    "Desktop", 
    "Documents", 
    "Downloads", 
    "Favorites", 
    "Links", 
    "Pictures", 
    "Saved Games", 
    "Searches", 
    "Videos", 
    ".git", 
    ".android", 
    ".IdealC15", 
    ".nuget", 
    ".oracle_jre_usage", 
    ".vs", 
    "Contacts" 
}; 

foreach (string dirPath in backupDirectories) 
{ 
    DirectoryInfo dirInfo = new DirectoryInfo(_path + "\\" + dirPath); 
    if (dirInfo.Exists) 
    { 
     foreach (string dirP in Directory.GetDirectories(dirInfo.FullName, "*", SearchOption.AllDirectories)) 
     { 
      DirectoryInfo dirI = new DirectoryInfo(dirP); 
      if (dirI.Exists) 
      { 
       string dir = dirP.Replace(_path, _configuration.Destination); 

       try 
       { 
        Directory.CreateDirectory(dir); 

        textBox2.Invoke((MethodInvoker) delegate 
        { 
         textBox2.AppendText("Create Directory: " + dir + Environment.NewLine); 
        }); 
       } catch (Exception e) 
       { 
        textBox2.Invoke((MethodInvoker) delegate 
        { 
         textBox2.AppendText("Could NOT Create Directory: " + dir + Environment.NewLine); 
        }); 
        continue; 
       } 

       foreach (FileInfo theFile in dirInfo.GetFiles("*", SearchOption.AllDirectories)) 
       { 
        string newPath = theFile.FullName; 
        string file = newPath.Replace(_path, _configuration.Destination); 

        try 
        { 
         File.Copy(newPath, file, true); 

         textBox2.Invoke((MethodInvoker) delegate 
         { 
          textBox2.AppendText("Create File: " + file + Environment.NewLine); 
         }); 
        } catch (Exception ex) 
        { 
         textBox2.Invoke((MethodInvoker) delegate 
         { 
          textBox2.AppendText("Could NOT Create File: " + file + Environment.NewLine); 
         }); 
        } 
       } 
      } 
     } 
    } 
} 

Я извиняюсь, если код грязный, но я буду описывать то, что он делает. Первый бит проверяет, существует ли резервная папка на внешнем диске.

Вторая часть говорит, какие папки мне нужно сделать резервными (если вы можете исправить это и сделать резервную копию всех каталогов с разрешениями, пожалуйста, помогите мне в этом).

Первый цикл запускает итерацию для каждого из backupDirectories. Второй цикл запускает итерацию для каждой из каталогов в каталоге резервного копирования. Третий цикл запускает итерацию для каждой из папок в каталоге резервного копирования.

Исключение составляет Directory.GetDirectories(dirInfo.FullName, "*", SearchOption.AllDirectories), и оно пытается получить доступ к C:\Users\MyName\Documents\My Music. Попытка доступа к нему в проводнике дает мне ошибку разрешений, хотя она не указана в проводнике при попытке перейти к «Документам» (я в Windows 10 Pro).

+0

Попробуйте предоставить разрешения сетевой службы для этой папки.Щелкните правой кнопкой мыши папку пользователя и перейдите к безопасности. – Kami

+0

В настоящее время моя учетная запись «Администраторы» и «СИСТЕМА» имеют только полный доступ к моему каталогу в «C: \ Users». Не уверен, что делать с «My Music». Также обратите внимание, что 'Моя музыка' отделена от' Music'. – SysVoid

+0

Если ваш код выдает исключение, потому что он недоступен, я не думаю, что вы можете что-то сделать, поскольку полномочия на код не превышают операционную систему. Но две вещи, которые вы можете сделать на стороне кода: (1) Проверьте 'Directory.GetAccessControl()' на проверку дочернего каталога, чтобы узнать, есть ли у вас доступ к Справочнику за ручку (этот вариант довольно сложно) (2) Использовать 'SearchOption.TopDirectoryOnly' вместо' SearchOption.AllDirectories', в сочетании с ** рекурсивным ** Поиск всех доступных каталогов для минимизации проблем с доступом – Ian

ответ

1

Как я рекомендовал, так как Operating System авторитет выше, чем применение, вполне вероятно, что вы не можете сделать больше, чем то, что Operating System позволит вам делать (то есть доступ или нет доступа к определенным folder).

Таким образом, доступность папок лучше всего решать на уровне Operating System.

Но вы все равно можете сделать две вещи на уровне программы, чтобы минимизировать ущерб при поиске предметов.

  1. Чтобы использовать Directory.AccessControl знать уровень доступа каталога, прежде чем сделать какой-либо запрос на него. Это не так просто, и есть подробные ответы об этом here, а также here.

  2. Чтобы свести к минимуму ущерба, нанесенным по вопросам несанкционированного доступа с помощью SearchOption.TopDirectoryOnly вместо SearchOption.AllDirectories, в сочетании с рекурсивным поиском всех доступных каталогов. Это, как вы можете закодировать его

    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 
        } 
    } 
    

    Функция выше минимизировать ущерб от несанкционированного доступа только к поддиректории, которые имеют проблемы. Все другие доступные каталоги могут быть возвращены.

+0

Извините, если я читаю это неправильно, но, конечно, в моей ситуации, когда 'Documents \ My Music' ломает его, это остановит процесс и вернет null? После того, как он попадает в 'Directory.GetDirectories (путь, searchPattern, SearchOption.TopDirectoryOnly) .ToList();' в 'My Documents', он увидит' My Music' и, следовательно, перестанет индексировать остальные папки в 'Documents'? – SysVoid

+0

Да, но поскольку это рекурсивно, при условии, что у вас есть родительский путь, и если родительский путь имеет другие дочерние элементы, это не повлияет на доступ к другим дочерним элементам, потому что 'null' обрабатывается в предыдущем вызове в рекурсивный вызов. – Ian

+0

Хорошо. Благодарю. Я попробую. :) – SysVoid