![](/img/trans.png)
[英]Can using FileShare.Delete cause a UnauthorizedAccessException?
[英]Did the behaviour of deleted files open with FileShare.Delete change on Windows?
我们多年来一直在使用以下代码。
/// <summary>
/// Opens a file and returns an exclusive handle. The file is deleted as soon as the handle is released.
/// </summary>
/// <param name="path">The name of the file to create</param>
/// <returns>A FileStream backed by an exclusive handle</returns>
/// <remarks>If another process attempts to open this file, they will recieve an UnauthorizedAccessException</remarks>
public static System.IO.FileStream OpenAsLock(string path)
{
var stream = TranslateIOExceptions(() => System.IO.File.Open(path, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.Delete));
System.IO.File.Delete(path);
return stream;
}
从内存中,此代码用于将文件保留在原位,直到 FileStream 关闭。 该技术被用作协作并发锁的一部分。
我发现了许多其他问题,这些问题让我认为过去的行为就像评论所描述的那样:文件保持原位,直到返回的文件流关闭。
使用 FileShare.Delete 会导致 UnauthorizedAccessException 吗?
但是,作为调查的一部分,我发现 Windows 的行为方式并非如此。 相反,一旦调用 File.Delete 就会删除该文件。 我还尝试重现 Hans 建议在上述链接中出现的错误,但没有成功。
class Program
{
static void Main(string[] args)
{
File.Open("test", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Delete);
File.Delete("test");
File.WriteAllText("test", "hello world");
Console.Write(File.ReadAllText("test"));
Console.ReadLine();
}
}
不幸的是,我们的单元测试可能会发现这种行为变化,但没有正确配置为在我们的环境中每晚运行,所以我不能确定它是否曾经运行过绿色。
这是行为的真正改变吗? 我们知道它是什么时候发生的吗? 是故意的(记录在案)吗?
非常感谢 Eryk 的提示。
事实证明,我们确实有几个单元测试可以捕捉到这种行为的变化,包括明确测试这种行为的测试。 我怀疑这些是在首先调查这种奇怪行为时添加的。
单元测试还没有发出警报,因为我们的测试机器运行的是比我的开发机器更旧的 Windows 10 版本。
我查看了 构建版本列表,不幸的是,这两个版本之间有两打以上的版本。 但是,我非常怀疑这个作为构建 17763.832 的一部分列出的“改进和修复” ,2019 年 10 月 15 日可用
解决了存储在具有备用数据流的集群共享卷 (CSV) 中的文件在您尝试删除它们后仍然存在的问题。 您可能还会在下次尝试访问或删除文件时收到“访问被拒绝”消息。
我不确定为什么特定于 CSV 的更改会影响我的系统,但描述与我看到的更改完全匹配。
至于具体的代码,结果发现我们的代码中从未使用过返回“FileStream”。 相反,我们依赖 IDisposable 接口,在“临界区”完成时关闭流,并解锁共享文件。
从技术上讲,这是一个重大变化,我现在执行以下操作:
// ...
public static IDisposable OpenAsLock(string path)
{
var stream = TranslateIOExceptions(() => System.IO.File.Open(path, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None));
return new FileBasedLock(stream, path);
}
// ...
internal class FileBasedLock : IDisposable
{
public FileBasedLock(FileStream stream, string path)
{
Stream = stream ?? throw new System.ArgumentNullException(nameof(stream));
Path = path ?? throw new System.ArgumentNullException(nameof(path));
}
public FileStream Stream { get; }
public string Path { get; }
public void Dispose()
{
Stream.Close();
try { File.Delete(Path); }
catch (IOException) { }
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.