繁体   English   中英

在 Windows 上使用 FileShare.Delete 打开已删除文件的行为是否发生了变化?

[英]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 关​​闭。 该技术被用作协作并发锁的一部分。

我发现了许多其他问题,这些问题让我认为过去的行为就像评论所描述的那样:文件保持原位,直到返回的文件流关闭。

我们能否在 Windows 中删除打开的文件?

使用 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 版本。

  • Build 17134.1304 肯定有旧行为。
  • Build 18363.657 肯定有新的行为。

我查看了 构建版本列表,不幸的是,这两个版本之间有两打以上的版本。 但是,我非常怀疑这个作为构建 17763.832 的一部分列出的“改进和修复” ,2019 年 10 月 15 日可用

解决了存储在具有备用数据流的集群共享卷 (CSV) 中的文件在您尝试删除它们后仍然存在的问题。 您可能还会在下次尝试访问或删除文件时收到“访问被拒绝”消息。

我不确定为什么特定于 CSV 的更改会影响我的系统,但描述与我看到的更改完全匹配。


至于具体的代码,结果发现我们的代码中从未使用过返回“FileStream”。 相反,我们依赖 IDisposable 接口,在“临界区”完成时关闭流,并解锁共享文件。

从技术上讲,这是一个重大变化,我现在执行以下操作:

  1. 创建具有独占句柄的锁定文件
  2. 返回一个实现 IDisposable 的新对象
  3. 等到一次性对象被释放,然后关闭流并尝试删除文件
// ...
    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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM