Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
587 views
in Technique[技术] by (71.8m points)

c# - Can using FileShare.Delete cause a UnauthorizedAccessException?

I'm opening a file with for reading that I had previously created in the user's %TEMP% folder, using the following code:

new FileStream(cacheFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);

On some user's computers, this sometimes throws an UnauthorizedAccessException with the message "Access to path ... is denied". I haven't been able to reproduce this. My initial guess is that an anti-virus or indexing engine is doing something funky, but I also noticed this code is using "FileShare.Delete", which I'm not sure should be there.

Is there a scenario where using "FileShare.Delete" leads to UnauthorizedAccessException ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, FileShare.Delete tends to cause this problem. Used by any program that runs in the background and scans files, file indexers and virus scanners are the common examples.

FileShare.Delete allows another process to delete the file, even though the background process still has the file opened and is reading from it. That other process will be oblivious that the file didn't actually disappear, for all it knows the file actually got deleted.

The trouble starts when that other process relies on the file actually being removed and does something else. Commonly triggered by creating a new file with the same name. Notably a very unwise way to save a file since it will cause complete data loss without a backup when the save fails, but this mistake is very common.

This will fail because the directory entry for the file is still present, it won't disappear until the last process that has the file opened closes the handle. Any other process that tries to open the file again will be slapped with error 5, "access denied". Including that process that deleted the file and tries to re-create it.

The workaround is to always use "transactional" saves, renaming the file before trying to overwrite it. Available in .NET with File.Replace(), in the native winapi with ReplaceFile(). Also easily done by hand, the workflow is:

  1. delete the backup file, stop if failed
  2. rename the old file to the backup filename, stop if failed
  3. write the new file using the original filename, rename backup back if failed
  4. delete the backup file, ignore failure

Step 2 ensures that there will never be any data loss, the original file stays intact if anything goes wrong. Step 4 ensures that FileShare.Delete will work as intended, that backup file will disappear eventually when other processes close their handles.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...