Directory.Delete(path, true) 会失败,因为 Windows API 的 DeleteFile 拒绝删除带 FILE_ATTRIBUTE_READONLY 标志的文件,即使递归参数为 true 也不会自动清除只读属性;必须先遍历所有文件和子目录(从内到外),用位运算清除只读位(保留其他属性),再执行删除。

为什么 Directory.Delete(path, true) 会失败
因为 .NET 的 Directory.Delete 默认调用 Windows API 的 DeleteFile,而该 API 拒绝删除带有 FILE_ATTRIBUTE_READONLY 标志的文件。即使你传了 true(递归),它也不会自动清除只读属性——它只是逐个尝试删,遇到只读文件就抛 UnauthorizedAccessException 或 IOException。
必须先遍历并清除只读属性
核心思路:不能依赖“强制删除”参数,得手动把所有文件和子目录的只读位去掉。注意两点:一是属性修改要从里往外(先子项后父项),二是目录本身也可能被设为只读(比如 Git 创建的空目录)。
实操建议:
- 用
Directory.GetFiles(path, "*", SearchOption.AllDirectories)获取全部文件路径,逐个调用File.SetAttributes(file, File.GetAttributes(file) & ~FileAttributes.ReadOnly) - 再用
Directory.GetDirectories(path, "*", SearchOption.AllDirectories)获取所有子目录(按深度降序排列),对每个目录执行同样操作:Directory.SetAttributes(dir, Directory.GetAttributes(dir) & ~FileAttributes.ReadOnly) - 最后才调用
Directory.Delete(path, true)
更安全的写法:用 FileAttributes 位运算而非直接赋值
别用 File.SetAttributes(file, FileAttributes.Normal) ——这会清掉隐藏、系统等其他属性,可能破坏程序或系统行为。正确做法是只清除只读位,保留其余属性不变:
var attrs = File.GetAttributes(file); File.SetAttributes(file, attrs & ~FileAttributes.ReadOnly);
同理适用于目录。另外,建议加 try/catch 包裹单个文件/目录的操作,避免一个权限问题导致整个删除中断。
遇到“访问被拒绝”仍失败?检查进程占用和权限
清除只读属性后还删不掉,常见原因有:
- 文件正被其他进程占用(如日志文件被记事本打开、DLL 被加载)→ 需提前关闭句柄或重启相关进程
- 当前用户没有删除权限(尤其在 Program Files 或系统目录下)→ 必须以管理员身份运行程序
- NTFS 权限中显式拒绝了“删除”权限 → 需用
DirectorySecurity修改 ACL,这不是简单属性操作能解决的
这类情况无法靠“递归+去只读”自动绕过,得结合具体场景做权限诊断或用户提示。










