UnauthorizedAccessException "Доступ к пути запрещен" из File.ReadAllBytes в LOCALAPPDATA

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

Исследование

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

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

Вот три объяснения этого исключения:

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

сценарий

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

исключение

System.UnauthorizedAccessException: доступ к пути "[отредактировано]" запрещен. в System.IO.__Error.WinIOError(Int32 errorCode, String MaybeFullPath) в System.IO.FileStream.Init (Строковый путь, режим FileMode, доступ FileAccess, права Int32, логические useRights, общий ресурс FileShare, размер буфера Int32, параметры FileOptions, параметры SECURITY_ATTRIBUTES secA, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) в System.IO.FileStream..ctor(Строковый путь, режим FileMode, доступ к FileAccess, FileShare share, Int32 bufferSize, параметры FileOptions, String msgPath, логическое значение bFromProxy, Boolean use Логический 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 ответ

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

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 для такого файла, но при попытке доступа к нему выдается исключение "Доступ запрещен", как вы описали.

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

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

Другие вопросы по тегам