簡體   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