【问题标题】:How to use File.WriteAllBytes() of C# to write on mounted drives?如何使用 C# 的 File.WriteAllBytes() 在已安装的驱动器上写入?
【发布时间】:2021-02-09 11:07:44
【问题描述】:

我喜欢使用System.IO.File.WriteAllBytes() 来保持简单。但似乎,这种方法不能到处使用。在我的本地系统上写它工作正常。

但是当我使用 System.IO.File.WriteAllBytes() 在 Windows 共享上写入时,它会生成一个空文件并失败并出现异常:

System.UnauthorizedAccessException: Access to the path '/var/windowsshare/file.bin' is denied.
---> System.IO.IOException: Permission denied

如果我查看https://github.com/dotnet/runtime/blob/c72b54243ade2e1118ab24476220a2eba6057466/src/libraries/System.IO.FileSystem/src/System/IO/File.cs#L421 的源代码 我发现以下代码在后台运行:

using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
{
    fs.Write(bytes, 0, bytes.Length);
}

如果我更改代码并使用 FileShare.None 而不是 FileShare.Read 它可以工作。所以我有一个解决方法,我必须记住System.IO.File.WriteAllBytes() 不防水(对吗?)。

不幸的是,我的分析最终提出了一些相关问题:

如果目标路径是可配置的,那么最佳实践是什么?开发人员必须避免 System.IO.File.WriteAllBytes() 还是系统管理员必须找到另一种方式来挂载共享? FileShare.Read 有什么问题? Windows 是否在 System.IO.File.WriteAllBytes() 正在写入时共享更改权限/锁定? 是否有一些安装 Windows 共享的提示?

更新 1

WriteAllBytes():

// WriteAllBytes() Throws System.UnauthorizedAccessException
System.IO.File.WriteAllBytes("/var/windowsshare/file.bin", bytes);

使用 C# 创建和移动

// Create local and move + optional overwrite works!
var tmp = Path.GetTempFileName(); // local file
System.IO.File.WriteAllBytes(tmp, bytes); // write local
System.IO.File.Move(tmp, "/var/windowsshare/file.bin", true); // optional overwrite

ls:

# ls -l /var/windowsshare/file.bin
-rw-rw-rw-. 1 apache apache 20 Feb  9 11:43 /var/windowsshare/file.bin
# ls -Z /var/windowsshare/file.bin
system_u:object_r:cifs_t:s0 /var/windowsshare/file.bin

挂载...

# mount -l
//1.2.3.4/windowsshare on /var/windowsshare type cifs (rw,relatime,vers=3.1.1,cache=strict,username=luke,domain=dom,uid=48,forceuid,gid=48,forcegid,addr=1.2.3.4,file_mode=0666,dir_mode=0777,soft,nounix,nodfs,nouser_xattr,mapposix,noperm,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1,_netdev)

# stat -f -c %T /var/windowsshare/file.bin
smb2

【问题讨论】:

  • 我猜这是一个安装在linux下的NTFS卷?它的安装方式有什么奇怪的地方吗:权限等?
  • 首先使用文件资源管理器开始写作,然后尝试使用资源管理器复制和编辑文件。这不是 c# 问题,而是正在使用的帐户的权限问题。
  • @jdweng 写入临时文件并移动它可以工作。 var tmp = Path.GetTempFileName(); System.IO.File.WriteAllBytes(tmp, bytes); System.IO.File.Move(tmp, target, true);
  • 您是管理员吗?您是从 VS 内部运行的吗?当您通常启动 VS 时,您没有管理员权限。要使用管理员从 VS 运行,您需要右键单击快捷方式并选择以管理员身份运行。我怀疑它在资源管理器中工作,因为您拥有管理员权限,而不是在 VS 中工作,因为您没有管理员权限。
  • @jdweng 该程序是作为 apache 用户在 Red Hat linux 上运行的 asp.net 核心服务。该服务在客户的网络中运行。所以我的VS与“Windows共享”没有任何联系。我没有使用资源管理器对其进行测试,但我可以说 System.IO.File.Move() 有效,而 System.IO.File.WriteAllBytes() 与用户 apache 均失败。

标签: c# network-programming mount writeallbytes


【解决方案1】:

Github 上的以下线程 (https://github.com/dotnet/runtime/issues/42790) 帮助了我。最后,我使用 nobrl 选项重新安装了我的 CIFS 共享。

在线程中他们也得出了使用FileShare.None 有效的结论,但根本原因似乎是我们使用的CIFS 服务器不支持字节范围锁。

我不确定这意味着什么,但在我的情况下,不需要多次写入文件,也不应该有两个进程尝试写入同一个文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 2022-06-19
    • 2019-04-07
    • 1970-01-01
    • 2019-09-15
    相关资源
    最近更新 更多