UnauthorizedAccessException "Доступ к пути запрещен" из File.ReadAllBytes в LOCALAPPDATA
Это исключение происходит периодически для одного и того же пользователя на одном компьютере при чтении файлов в %LOCALAPPDATA%
,
Исследование
Я проверил все возможные дубликаты, предлагаемые в настоящее время под этим названием (их много). Есть один, связанный с чтением зашифрованного файла AES, который не имеет ответа; и я не думаю, что это применимо, так как эти файлы не зашифрованы.
Большинство из них связаны с записью файлов (но я читаю файл) или являются очевидными причинами, описанными в MSDN для File.ReadAllBytes(строка).
Вот три объяснения этого исключения:
- "Эта операция не поддерживается на текущей платформе" - я не знаю, что это значит; но учитывая, что это иногда работает для одного и того же пользователя на той же машине (я объясню ниже), я думаю, что могу исключить это.
- "путь указан каталог" - как вы увидите из кода ниже, вызов выполняется в рамках проверки
File.Exists
Я думаю, что могу исключить это. - "Звонящий не имеет необходимого разрешения". Это обычное объяснение этого исключения, и я подозреваю, что я получаю какое-то "дополнительное дело" по этому поводу.
сценарий
Это происходит, когда приложение, которое работает как пользователь домена, читает файл в подпапке %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 для такого файла, но при попытке доступа к нему выдается исключение "Доступ запрещен", как вы описали.
Сложно сказать, относится ли эта конкретная ситуация к вашему делу, но это может быть так.
Моя точка зрения в основном такова: вы должны ожидать такие исключения (а также исключения типа "файл уже используется") и обрабатывать их, повторяя попытку. Они могут произойти по разным причинам вне вашего контроля.