UnauthorizedAccessException «Доступ к пути запрещен» из File.ReadAllBytes в LOCALAPPDATA - PullRequest
0 голосов
/ 27 апреля 2018

Это исключение возникает периодически для одного и того же пользователя на одном компьютере при чтении файлов в %LOCALAPPDATA%.

Research

Я проверил все возможные дубликаты, предлагаемые в настоящее время под этим названием (их много). Есть один, связанный с чтением зашифрованного файла AES , который не имеет ответа; и я не думаю, что это применимо, так как эти файлы не зашифрованы.

Большинство из них связаны с записью файлов (но я читаю файл) или являются очевидными причинами, описанными в MSDN для File.ReadAllBytes (string) .

Существует три объяснения этого исключения:

  1. «Эта операция не поддерживается на текущей платформе» - я не знаю, что это значит; но учитывая, что это иногда работает для одного и того же пользователя на одной и той же машине (я объясню ниже), я думаю, что могу исключить это.
  2. " путь указан каталог" - как вы увидите из кода ниже, вызов выполняется с проверкой File.Exists, поэтому я думаю, что могу исключить это.
  3. "У вызывающей стороны нет необходимого разрешения." Это обычное объяснение этого исключения, и я подозреваю, что я получаю какой-то «крайний случай» этого.

Сценарий

Это происходит, когда приложение, работающее в качестве пользователя домена, читает файл в подпапке %LOCALAPPDATA% того же пользователя (для которого у этого пользователя не должно быть никаких разрешений на чтение файлов). Подпапки внутри этого просто следуют обычной структуре «CompanyName» \ «ApplicationName», и к подпапкам не применяются дополнительные разрешения (мы просто используем папку, чтобы наши файлы не попадали в чужие файлы).

Исключение

System.UnauthorizedAccessException: доступ к пути ' [отредактировано] ' есть отказано. в System.IO .__ Error.WinIOError (Int32 errorCode, String MaybeFullPath) в System.IO.FileStream.Init (String path, FileMode режим, доступ к FileAccess, права Int32, логическое использование прав, FileShare поделиться, Int32 bufferSize, опции FileOptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) в System.IO.FileStream..ctor (String path, Режим FileMode, доступ к FileAccess, общий доступ к FileShare, размер буфера Int32, Опции FileOptions, Строка msgPath, Логическое значение bFromProxy, Логическое значение useLongPath, Boolean checkHost) в System.IO.File.InternalReadAllBytes (Строковый путь, логический checkHost)
на код ниже

Код

        // Note that filename is within %LOCALAPPDATA%
        if (File.Exists(fileName))
        {
            var readAllBytes = File.ReadAllBytes(fileName); // exception here
            // etc...
        }

Доказательство того, что оно прерывистое

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

  • Приложение работает, тогда
  • Это исключение возникает (возможно, несколько раз, причем задержки повторов экспоненциально увеличиваются каждый раз: 1 минута, 2 минуты, 4 минуты и т. Д.), Затем
  • Приложение снова работает

Я не верю, что какие-либо существенные изменения (например, разрешения) произошли в файловой системе для ее исправления. Мне интересно, может ли это быть вызвано проблемой дополнительных прав доступа, например, если срок действия их пароля истекает или он был недавно изменен.

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

Вопрос

Может кто-нибудь дать мне авторитетное объяснение причины этого, сверх того, о чем я уже догадался, или подтвердить, что это такое?

1 Ответ

0 голосов
/ 27 апреля 2018

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

public class Program {
    static string _target = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "test", "test.txt");
    static void Main(string[] args) {
        File.Create(_target).Dispose();
        ProcessFile();

        // below throws access denied
        if (File.Exists(_target))
            Console.WriteLine(File.ReadAllText(_target));
        Console.ReadKey();
    }

    static void ProcessFile() {
        // open and abandon handle
        var fs = new FileStream(_target, FileMode.Open, FileAccess.Read, FileShare.Delete);
        // delete
        File.Delete(_target);
    }        
}  

Здесь мы создаем новый файл под %LOCALAPPDATA% и открываем его с FileShare.Delete, но не закрываем. FileShare.Delete разрешает последующее удаление файла, но файл не будет фактически удален, пока все дескрипторы к нему не будут закрыты.

Затем мы переходим к File.Delete, который фактически не удаляет файл, но помечает его для удаления, потому что у нас все еще есть дескриптор открытого файла.

Теперь, File.Exists возвращает true для такого файла, но попытка доступа к нему вызывает исключение "Отказано в доступе", как вы описали.

Трудно сказать, относится ли эта конкретная ситуация к вашему делу, но это может быть так.

Моя точка зрения в основном такова: вы должны ожидать такие исключения (а также исключения типа «файл уже используется») и обрабатывать их, повторяя попытку. Они могут произойти по разным причинам вне вашего контроля.

...