DirectorySecurity 添加用户读写权限需先获取现有安全描述符,添加 FileSystemAccessRule 并设置正确继承与传播标志,再调用 Directory.SetAccessControl 生效;非 Windows 平台不支持该 API。

用 DirectorySecurity 添加用户读写权限最直接
Windows 文件系统 ACL 不是靠“改属性”实现的,而是通过 DirectorySecurity 对象增删 FileSystemAccessRule 条目。直接调用 Directory.SetAccessControl 才算真正生效,只改 DirectoryInfo.Attributes 没用。
- 必须先获取现有安全描述符:
var sec = Directory.GetAccessControl(path),不能 new 一个空的 - 添加规则时注意
FileSystemRights枚举值:比如FileSystemRights.ReadAndExecute包含遍历+读文件+执行,但不含写入;要写必须显式加Modify或拆成Write+ReadAndExecute - 继承标志很关键:
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit才能让子目录和文件都继承,漏掉任一都会导致权限不向下传递 - 别用
AccessControlType.Allow覆盖已有拒绝规则——Windows 拒绝优先级高于允许,得先清理冲突的Deny条目
UnauthorizedAccessException 多半是没提权或路径不对
这个异常不是代码写错了,而是进程没拿到足够权限去修改目标文件夹的 DACL。常见于:服务账户运行、非管理员用户执行、UAC 隔离、或路径指向系统保护目录(如 C:\Program Files)。
- 检查当前进程是否以管理员身份运行:
WindowsIdentity.GetCurrent().Owner对比WellKnownSidType.BuiltinAdministratorsSid可粗略判断 - 避免硬编码绝对路径;用
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)这类 API 获取有写权限的公共位置 - 如果必须操作受保护路径,不要试图绕过 UAC——改用安装器提权,或把权限设置逻辑移到安装阶段
递归设置权限时,PropagationFlags 容易设反
想让子目录和文件都获得新权限,光设 InheritanceFlags 不够,还必须配对设置 PropagationFlags。设错会导致:子目录有了权限,但里面文件没继承;或者反过来,文件有了,子目录没继承。
- 完整继承组合是:
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit+PropagationFlags.InheritOnly(用于容器本身不应用,只传给后代) - 若希望当前文件夹也应用该规则,再加
PropagationFlags.None——但此时要小心:这会让当前目录权限叠加,可能和原有规则冲突 - 批量处理前建议先用
Get-AclPowerShell 命令验证原始 ACL 结构,避免盲目覆盖
.NET Core/.NET 5+ 在 Linux/macOS 上不支持 ACL 设置
DirectorySecurity 和相关类型在非 Windows 平台只是存根(stub),调用会抛 PlatformNotSupportedException。这不是 bug,是设计如此——Linux 用 POSIX 权限(chmod)和扩展属性(xattr),macOS 还多一层 ACL(但格式不同)。
- 跨平台项目里别封装统一的“设权限”方法;检测运行时:
OperatingSystem.IsWindows()再分支处理 - Linux 下真要控制访问,得调用
Process.Start("chmod", "755 /path"),但注意:这只能设基础 rwx,没法精确到用户/组粒度 - macOS 若需等效功能,得用
chmod -R +a "user:xxx:allow read,write",但 .NET 没内置封装,只能走 shell
ACL 是 Windows 特有的安全模型细节,写的时候就得接受它和 POSIX 的根本差异——不是语法问题,是权限抽象层不一样。真要跨平台精细控权,得换思路:用服务隔离、沙箱或配置中心做访问决策,而不是依赖文件系统底层。










