.NET中File.GetAccessControl只能获取文件当前所有者(Owner),无法获取创建者,因为NTFS不存储“创建者”元数据;所有者可被任意修改,与创建行为无关;需通过SecurityIdentifier.Translate转换SID为用户名,并捕获IdentityNotMappedException处理无法映射的情况。

Windows平台下用File.GetAccessControl读取文件所有者
在Windows上,文件所有者(Owner)不等于创建者(Creator),但系统通常把创建者设为初始所有者。.NET本身不提供直接获取“创建者”的API——因为NTFS没有独立存储“创建者”字段,只有“所有者”(Owner)和“审计项”(SACL)中可能记录操作者,而后者需提前配置且不可靠。
所以实际能稳定拿到的是所有者SID,再通过SecurityIdentifier.Translate转成可读用户名:
var acl = File.GetAccessControl(@"C:\test.txt");
var owner = acl.GetOwner(typeof(SecurityIdentifier));
if (owner != null)
{
try
{
var name = owner.Translate(typeof(NTAccount)).Value;
Console.WriteLine($"Owner: {name}"); // 如 "DOMAIN\user"
}
catch (IdentityNotMappedException)
{
Console.WriteLine($"Owner SID: {owner.Value}");
}
}
- 必须有读取文件安全描述符的权限,否则抛
UnauthorizedAccessException - 跨域或本地内置账户(如
S-1-5-18代表SYSTEM)可能无法翻译,需捕获IdentityNotMappedException - 该方法不返回创建时间或创建动作的用户,仅反映当前ACL中的Owner字段
为什么拿不到真正的“创建者”信息
NTFS文件系统不保存“谁创建了这个文件”这一元数据。创建时写入的Owner字段可被任意修改,且后续任何有足够权限的用户都能调用SetOwner覆盖它。所谓“创建者”,只是创建时刻Owner字段的快照,之后就与创建行为无关了。
- 资源管理器“属性→安全→高级”里看到的“所有者”就是这个值,不是审计日志
- 若需追溯创建行为,得依赖Windows事件日志(Event ID 4663 + SACL配置),但那是系统级审计,不在.NET文件I/O范畴内
- 第三方工具(如Sysinternals Process Monitor)能实时捕获创建动作,但无法回溯已存在的文件
Linux/macOS下无对应概念
.NET 6+支持跨平台,但在非Windows系统上调用File.GetAccessControl会直接抛PlatformNotSupportedException。POSIX系统只有UID/GID(所有者/所属组),没有“创建者”一说,且UID在文件生命周期中也不会自动记录创建动作。
- 用
File.GetAttributes或File.GetCreationTime只能知道时间,不知道人 - 若运行在Linux容器中且挂载了Windows卷,仍需走Windows ACL路径,但受限于容器权限模型,大概率失败
替代思路:从父目录继承或结合日志分析
如果业务场景真需要推断创建者,可考虑间接方式:
- 检查文件所在目录的默认ACL,某些企业环境会配置“新文件继承父目录Owner”策略(但.NET无法直接查此策略)
- 若文件由你自己的程序创建,应在创建后立刻用
File.SetAccessControl写入自定义标识(比如在扩展属性里存用户名,但需额外存储机制) - 配合ETW或Windows事件日志(需管理员开启对象访问审计),筛选
4663事件并过滤“Create”操作——但这属于系统运维范畴,不是纯代码能解决的
真正可靠的“创建者”永远不在文件自身元数据里,而在创建那一刻的上下文。代码能读的只有Owner,别把它当成创建者用。










