可以用FileShare.Delete引起UnauthorizedAccessException?可以用、FileShare、UnauthorizedAccessException、Delete

2023-09-04 13:11:43 作者:收起伱的谎言

我打开一个文件进行读取,我有用户的%TEMP%文件夹中创建pviously $ P $,使用下面的code:

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

在一些用户的计算机上,这有时会抛出消息访问路径......被拒绝的UnauthorizedAccessException。我一直无法重现此。我最初的猜测是,防病毒或索引引擎是做一些古怪,但我也注意到了这个code使用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.

有没有在那里使用FileShare.Delete导致UnauthorizedAccessException?一个场景

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

推荐答案

是的,FileShare.Delete往往会造成这个问题。用于那些在后台运行,并扫描文件,文件索引和病毒扫描是常见的例子。任何程序

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允许的另一个的过程中要删除的文件,即使后台进程仍然有打开的文件,并从中读取。其他进程将无视该文件并没有真正消失,所有它知道的文件实际上删除了。

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.

这将失败,因为该文件的目录项仍然是present,它不会消失,直到有该文件的最后一个进程打开关闭句柄。试图再次打开该文件,任何其他进程将错误5被掌掴,拒绝访问。包括删除的文件,并试图重新创建它的进程。

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.

解决方法是始终用交易的扑救,试图覆盖它之前重命名文件。可在.NET与File.Replace(),与ReplaceFile本地WINAPI()。也很容易通过手工完成的工作流程是:

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:

删除备份文件,停止,如果失败 重命名旧文件备份到备份文件名,如果停止失败 编写使用原始文件名新的文件,重命名备份回来,如果失败 删除备份文件,忽略失败

步骤2确保绝不会有任何数据丢失,原始文件如果有什么不顺心保持不变。第4步确保FileShare.Delete会达到预期效果,该备份文件会消失,最终在其他进程关闭其句柄。

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.

 
精彩推荐
图片推荐