5

在遵循论坛提示 [1] 后,我在 Windows 中执行文件时遇到文件权限问题,但我不明白为什么。也许你们可以帮忙。

我通过执行文件(读取控制台输出)来检查文件的横幅,然后使用 FileStream 打开同一个文件以供读取:

public void fileMD5(string filename) {
  if (!File.Exists(filename)) return NT.Fail("File does not exist: " + filename);

  BinaryReader stream = new BinaryReader(File.Open(filename,
      FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
  int bufferSize = 4096;
  byte[] buffer = new byte[bufferSize];
  int readBytes;
  while ((readBytes = stream.Read(buffer, 0, bufferSize)) > 0) {
    md5Hasher.TransformBlock(buffer, 0, readBytes, buffer, 0);
  }
  stream.Close();
}

fileMD5('sample.exe');

每隔一段时间我就会得到“文件正在被另一个进程使用”。从 Wikipedia 我知道 Windows 将锁定执行拒绝写访问的文件 [2],但我只是在阅读。当我尝试打开它时,该过程应该已经停止。

从论坛帖子看来,添加 FileShare.ReadWrite 会有所帮助,而且似乎确实如此:

FileStream stream = File.Open('sample.exe', 
    FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

但我不明白为什么。这里有我看不到的比赛条件吗?

此外,使用 FileShare.ReadWrite 而不是默认值(我猜是 FileShare.Read),File.Open 调用似乎要快得多。

[1] http://www.xtremevbtalk.com/archive/index.php/t-192118.html

[2] http://en.wikipedia.org/wiki/File_locking#In_Microsoft_Windows

4

4 回答 4

12

当您不指定 FileShare 参数时,此选项的默认值为 FileShare.None,实际上 File 类中的代码只是执行以下操作:

public static FileStream Open(string path, FileMode mode, FileAccess access)
{
    return File.Open(path, mode, access, FileShare.None);
}

关于性能,我只能想象指定 FileShare.ReadWrite 意味着 Windows 不需要获取文件锁定。

至于“文件正在被另一个进程使用”错误,如果您将流变量的使用包装在 using 块中,以便在您完成后立即处理流,那么这个问题会消失吗?

using (var stream = File.Open('sample.exe', FileMode.Open, FileAccess.Read))
{
  //do something with the stream here
}
于 2011-08-10T08:21:35.160 回答
2

您应该关闭您的 FileStream,然后再打开一个新的 FileStream。

当应用程序想要共享文件时,需要 FileShare,而不仅仅是一个应用程序或一个应用程序同时具有多个读取器或写入器。

为什么?当每个人都可以同时阅读和写作时,就会变得一团糟。在这种情况下,您最好明确设置它,以便清楚它会变得混乱。:)

于 2011-08-10T08:17:47.467 回答
1

它与底层的 Windows API CreateFile 标志有关。 有关概述, 参见http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx,http://blogs.msdn.com/b/larryosterman/archive/2004/ 05/13/131263.aspx 用于解释 NT(及后续)如何使用 FILE_SHARE_DELETE 加载 execs

尤其是这个

http://blogs.msdn.com/b/oldnewthing/archive/2004/05/11/129759.aspx

有关共享权限和所需访问权限如何组合在一起的详细说明!

于 2011-08-10T08:23:26.993 回答
1

似乎指定错误的 FileShare 会禁止您访问文件。如果您指定FileShare.Read但某个其他应用程序当前对该文件具有写访问权限,则您无法访问该文件,因为您的 FileShare.Read 当前无法满足。FileShare.ReadWrite 限制较少,因为它更容易满足。来源:http: //blogs.msdn.com/b/oldnewthing/archive/2004/05/11/129759.aspx

于 2012-11-07T15:02:00.137 回答