为什么 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,这不是简单属性操作能解决的
这类情况无法靠“递归+去只读”自动绕过,得结合具体场景做权限诊断或用户提示。
