6

This exception is occurring intermittently for the same user for the same machine, when reading files within %LOCALAPPDATA%.

Research

I have checked all the possible duplicates currently offered by this title (there are a lot). There is one relating to reading an AES encrypted file which has no answer; and I don't believe applies, since these files are not encrypted.

Most of them are to do with writing files (but I'm reading a file), or are the obvious causes as documented on MSDN for File.ReadAllBytes(string).

The three explanations for this exception on there are:

  1. "This operation is not supported on the current platform" - I don't know what that means; but given that this works sometimes for the same user on the same machine (I'll explain below), I think I can rule this out.
  2. "path specified a directory" - as you'll see from the code below, the call is made within a check of File.Exists, so I think I can rule this out.
  3. "The caller does not have the required permission." This is the usual explanation for this exception, and I suspect I'm getting some kind of "fringe case" of this.

Scenario

This is occurring when an application which is running as a domain user is reading a file inside a subfolder of %LOCALAPPDATA% of the same user (for which there should be no permission issues for that user to read files). The subfolders within that just follow the normal "CompanyName"\"ApplicationName" structure, and there are no additional permissions applied on the sub folders (we're just using the folder to keep our files away from other people's).

Exception

System.UnauthorizedAccessException: Access to the path '[redacted]' is denied. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) at System.IO.File.InternalReadAllBytes(String path, Boolean checkHost)
at the code below

Code

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

Proof that it is intermittent

And I can prove from the combination of our error logs, and other information that this is working most of the time, and I can prove the following sequence of events for a particular combination of machine and user:

  • The application works, then
  • This exception occurs (maybe several times, with retry delays exponentially increasing each time: 1minute, 2minutes, 4minutes, etc), then
  • The application works again

I don't believe that any material change (e.g. permissions) will have occurred to the file system in order to fix it. I'm wondering whether this might be caused by a fringe permissions issue, for example, if their password is about to expire, or has recently been changed.

I have a specific example when I noticed this error happening, and I advised the user to reboot their machine, and the problem went away.

Question

Can anyone give me an authoritative explanation of the cause of this, above what I've already guessed, or to confirm what it is?

Richardissimo
  • 5,596
  • 2
  • 18
  • 36
  • 1
    Are there any other parts of your program that might write to the file, or any other programs that might have an exclusive lock on the file (eg with Excel, this will mostly happen when the user has this file open). Do you have any filehandles open somewhere? – Icepickle Apr 27 '18 at 08:49
  • No, the file has been copied into that folder specifically for processing by the application in question, and is not somewhere that is exposed to the user through the application; so there is no reason to believe the user is even aware of the folder or its contents. – Richardissimo Apr 27 '18 at 08:50
  • Can you confirm that `fileName` is local to the function and not subject to updates from any other source whilst your code is running? – Damien_The_Unbeliever Apr 27 '18 at 08:53
  • What type of application is this - Windows or Web? – Reinstate Monica Cellio Apr 27 '18 at 08:54
  • 1
    @Archer, thanks, I've just added a tag for Windows application. – Richardissimo Apr 27 '18 at 08:55
  • @Damien_The_Unbeliever The filename variable is local and is not modified. – Richardissimo Apr 27 '18 at 08:56
  • Other than the obvious things you've already listed I can only think that you open the file at some point and don't close it, but I'd also expect a different exception in that situation. Just out of curiosity, can you append a timestamp (or something unique) onto the filename each time you write? I know that's no good for your application but it would rule out or confirm the possibility that it's that specific file that has an issue. – Reinstate Monica Cellio Apr 27 '18 at 08:58
  • 1
    One other obvious source of intermittent file access errors is AV software. Is it possible that this user has different AV running on their machine versus others? – Damien_The_Unbeliever Apr 27 '18 at 08:59
  • @Damien_The_Unbeliever No, everyone has the same AV; but that's definitely an interesting thought. Thanks for that. – Richardissimo Apr 27 '18 at 09:01
  • Can the user open this file e.g. in the notepad? I guess we have to determine whether this is a general permissions issue or your app's issue. Maybe your app has some security constraints or tricky `AppDomain`s etc. – dymanoid Apr 27 '18 at 09:39
  • @Damien_The_Unbeliever After further thought, I don't think it's the AV, since that usually applies when a file is first created. This code has a retry delay of 1 minute, then 2 minutes the next time, then 4 minutes, etc; and I can see this exception, then the 1 minute delay, then the exception again, then the 2 minute delay, then the exception, then the 4 minute delay, then the exception. I doubt the AV would still be a problem after that kind of delay. – Richardissimo Apr 27 '18 at 09:59
  • @dymanoid They *could* open one of the files; but as I mentioned in an earlier comment, the user has no visibility of the folder that this is put in, and would have no reason to know that it even exists. The app is a very simple system tray app, there are no special AppDomains and we have no security permissions. We just put the file in LOCALAPPDATA, which is in the user's profile area, so is specific to them. – Richardissimo Apr 27 '18 at 10:03

1 Answers1

1

The question is too broad, but I want to point out that there are other reasons for access denied exception besides you listed. For example, consider this simple program:

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

Here we create new file under %LOCALAPPDATA%, and open it with FileShare.Delete, but not closing. FileShare.Delete allows subsequent deletion of the file, but file will not be actually deleted until all handles to it are closed.

Then we proceed with File.Delete, which does not actually delete file but marks it for deletion, because we still have open file handle to it.

Now, File.Exists returns true for such file, but trying to access it throws "Access denied" exception as you described.

Whether this specific situation is relevant to your case is hard to tell, but it might be.

My point mainly is: you should expect such exceptions (and also "file already in use" kind of exceptions) and handle them by retrying. They can happen for various reasons outside of your control.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • Thanks, this is certainly useful to know. In case it's relevant, the file only gets there with a `File.Copy` and we only read it with the `File.ReadAllBytes` from the question, so there's no streams lying about on our part - nothing else has a reason to be looking at that file, and we aren't using threading. I guess that for a pending delete, the actual file deletion would occur when they logoff, or certainly if they reboot; so that would be consistent with what we're seeing in these rare, intermittent cases. – Richardissimo Apr 27 '18 at 12:09
  • Regarding the final point you made, we *are* expecting the exceptions, and logging them and retrying, which is how I'm able to give a detailed timeline in the question. Now I just need to identify what's causing it, so I can fix it :) – Richardissimo Apr 27 '18 at 12:14