UnauthorizedAccessException “L’access au chemin est refusé” à partir de File.ReadAllBytes dans LOCALAPPDATA

Cette exception se produit par intermittence pour le même utilisateur pour la même machine, lors de la lecture de fichiers dans %LOCALAPPDATA% .

Recherche

J’ai vérifié tous les doublons possibles actuellement proposés par ce titre (il y en a beaucoup). Il y en a un relatif à la lecture d’un fichier crypté AES qui n’a pas de réponse; et je ne crois pas que cela s’applique, car ces fichiers ne sont pas cryptés.

La plupart d’entre eux ont à voir avec l’écriture de fichiers (mais je lis un fichier), ou sont les causes évidentes telles que documentées sur MSDN pour File.ReadAllBytes (chaîne) .

Les trois explications pour cette exception sont:

  1. “Cette opération n’est pas prise en charge sur la plate-forme actuelle” – je ne sais pas ce que cela signifie; mais étant donné que cela fonctionne parfois pour le même utilisateur sur la même machine (je vais l’expliquer ci-dessous), je pense que je peux l’exclure.
  2. path a spécifié un répertoire” – comme vous le verrez dans le code ci-dessous, l’appel est effectué dans une vérification de File.Exists , donc je pense que je peux l’exclure.
  3. “L’appelant n’a pas l’autorisation requirejse.” Ceci est l’explication habituelle de cette exception, et je soupçonne que je reçois une sorte de “cas marginal” de cela.

Scénario

Cela se produit lorsqu’une application qui s’exécute en tant qu’utilisateur de domaine lit un fichier dans un sous-dossier de %LOCALAPPDATA% du même utilisateur (pour lequel il ne doit y avoir aucun problème d’autorisation pour que cet utilisateur puisse lire les fichiers). Les sous-dossiers qui s’y trouvent suivent simplement la structure normale “CompanyName” \ “ApplicationName”, et aucune autre autorisation n’est appliquée sur les sous-dossiers (nous utilisons simplement le dossier pour garder nos fichiers à l’écart des autres utilisateurs).

Exception

System.UnauthorizedAccessException: L’access au chemin ‘ [expurgé] ‘ est refusé. at System.IO .__ Error.WinIOError (Int32 errorCode, Ssortingng MaybeFullPath) à System.IO.FileStream.Init (Chemin de la chaîne, mode FileMode, access FileAccess, droits Int32, Boolean useRights, partage FileShare, Int32 bufferSize, options FileOptions, SECAURIT_ATTRIBUTES secAttrs , Ssortingng msgPath, booléen bFromProxy, booléen useLongPath, booléen checkHost) à System.IO.FileStream..ctor (chemin de chaîne, mode FileMode, access FileAccess, partage FileShare, Int32 bufferSize, options FileOptions, chaîne msgPath, booléen bFromProxy, Boolean useLongPath, Boolean checkHost) à System.IO.File.InternalReadAllBytes (chemin de chaîne, contrôle booléen checkHost)
au code ci-dessous

Code

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

Preuve que c’est intermittent

Et je peux prouver par la combinaison de nos journaux d’erreurs et d’autres informations que cela fonctionne la plupart du temps, et je peux prouver la séquence d’événements suivante pour une combinaison particulière de machine et d’utilisateur:

  • L’application fonctionne, puis
  • Cette exception se produit (peut-être plusieurs fois, avec des délais de relance augmentant de manière exponentielle à chaque fois: 1 minute, 2 minutes, 4 minutes, etc.), puis
  • L’application fonctionne à nouveau

Je ne crois pas qu’un changement matériel (par exemple, des permissions) se soit produit dans le système de fichiers pour y remédier. Je me demande si cela pourrait être dû à un problème lié aux permissions marginales, par exemple, si leur mot de passe est sur le point d’expirer ou s’il a été récemment modifié.

J’ai un exemple spécifique lorsque j’ai remarqué que cette erreur se produisait et j’ai conseillé à l’utilisateur de redémarrer sa machine, et le problème est parti.

Question

Quelqu’un peut-il me donner une explication officielle de la cause de cela, au-dessus de ce que j’ai déjà deviné, ou pour confirmer ce que c’est?

La question est trop large, mais je tiens à souligner qu’il ya d’autres raisons pour lesquelles l’access a été refusé, à part vous. Par exemple, considérons ce programme simple:

 public class Program { static ssortingng _target = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "test", "test.txt"); static void Main(ssortingng[] 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); } } 

Ici, nous créons un nouveau fichier sous %LOCALAPPDATA% , et nous l’ouvrons avec FileShare.Delete , mais pas en fermant. FileShare.Delete permet la suppression ultérieure du fichier, mais le fichier ne sera pas réellement supprimé tant que toutes les poignées ne seront pas fermées.

Ensuite, nous File.Delete avec File.Delete , qui ne supprime pas réellement le fichier mais le marque pour la suppression, car nous avons toujours un descripteur de fichier ouvert.

Maintenant, File.Exists renvoie true pour un tel fichier, mais en essayant d’y accéder, lève une exception “Accès refusé” comme vous l’avez décrit.

Il est difficile de dire si cette situation spécifique est pertinente pour votre cas, mais cela pourrait être le cas.

Mon point principal est le suivant: vous devez vous attendre à de telles exceptions (et aussi à des types d’exceptions du type “fichier déjà utilisé”) et les traiter en réessayant. Ils peuvent se produire pour diverses raisons indépendantes de votre volonté.