【发布时间】: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