为什么第二个进程无法读取允许通过 FileShare.Read 读取的文件?

问题描述 投票:0回答:1

以下代码预计将像 Excel 一样工作,并通知用户他们只能以只读模式访问电子表格:

  1. 第一个进程打开文件并获得写访问权限。它将用户信息保留在
    .lock
    文件中
  2. 任何其他进程只能读取该信息。它从
    .lock
    文件中读取用户信息,以便用户可以例如与访问该文件的人讨论

为了重现,运行程序2次,实例1无需调试即可运行。运行附加调试器的第二个实例以查看

IOException

using System;
using System.IO;
using System.Text;

namespace SingleUser
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string lockFileName = ".lock";

            // Make sure that CreateNew can be used in the next step
            try
            {
                File.Delete(lockFileName);
            }
            catch (IOException) { }
            
            try
            {
                // First process enters here and gets access
                using (var lockfile = File.Open(lockFileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read))
                {
                    using (var writer = new StreamWriter(lockfile, Encoding.UTF8, 256, true))
                    {
                        string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                        writer.WriteLine(userName);
                        writer.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    }

                    // IOException: The segment is already unlocked
                    // lockfile.Unlock(0,lockfile.Length);

                    Console.WriteLine("You can access the data. Press Enter to stop working with the file.");
                    Console.ReadLine();
                }
            }
            catch (IOException e)
            {
                // Second process enters here and gets info about the user who is working with the data
                using (var infofile = File.Open(lockFileName, FileMode.Open, FileAccess.Read)) // <-- fails
                {
                    using (var reader = new StreamReader(infofile, Encoding.UTF8, false, 256, true))
                    {
                        string user = reader.ReadLine();
                        string time = reader.ReadLine();
                        Console.WriteLine($"{user} works on the file since {time}.");
                    }
                }
                Console.WriteLine("You can't modify the data. Press Enter to stop.");
                Console.ReadLine();
            }
        }
    }
}

由于行中出现 IOException,上述代码不起作用

using (var infofile = File.Open(lockFileName, FileMode.Open, FileAccess.Read))  // <-- fails

但是Notepad++可以毫无问题地打开文件并且复制也可以。所以,不知何故似乎可以读取该文件。

正如 Hans Passant 证实的那样

如果记事本可以读取该文件,那么您也可以,显然该程序没有对该文件设置读取锁定。

我已经尝试过

Unlock()
,如这里提到的

lockfile.Unlock(0,lockfile.Length);
在上面代码中注释的地方,但这给了我

IOException:该段已解锁

我已阅读

汉斯·帕桑特的回答,其中说

首先尝试使用 FileAccess.ReadWrite 和 FileShare.Read 打开文件。如果没有收到 IOException,则您将拥有该文件的独占写入访问权限。其他进程可以读取该文件,但永远无法获得写入权限。

恕我直言,这正是我在这里尝试的。

如果这很重要的话,我仍在使用 .NET Framework 4.7.2。该文件是本地文件(但网络文件也一样)。

那么,有人可以澄清为什么我的代码不起作用以及如何使其工作吗?

c# file locking .net-4.7.2
1个回答
0
投票
正在读取文件的第二个进程需要允许第一个进程对文件进行更改。因此,FileShare 必须设置为

FileShare.ReadWrite

如果您只有

read 访问权限并授予其他人 write 访问权限,这看起来有点疯狂,但这与权限无关。像这样思考:您拥有读取访问权限并且可以处理某人的写入访问权限。

© www.soinside.com 2019 - 2024. All rights reserved.