You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#中获取文件最后修改人(适配Azure AD环境)

解决Azure AD环境下获取文件最后修改人问题

首先要明确:你之前的代码获取的是文件所有者,并非文件的最后修改人。在Azure AD环境下,由于身份标识体系的差异,直接将SID转换为NTAccount会抛出"部分或全部身份引用无法转换"的异常,以下是几种可行的替代方案:

方案1:先获取SID,兼容无法转换的身份

先获取文件所有者的SID,再尝试转换为NTAccount,若转换失败则直接返回SID字符串,避免异常:

FileSecurity fileSecurity = file.GetAccessControl();
IdentityReference ownerSid = fileSecurity.GetOwner(typeof(SecurityIdentifier));
string ownerName;
try
{
    ownerName = ownerSid.Translate(typeof(NTAccount)).Value;
}
catch (IdentityNotMappedException)
{
    // Azure AD身份无法转换时直接返回SID
    ownerName = ownerSid.Value;
}

方案2:使用WMI查询文件的最后修改人

通过WMI的Win32_File类可以直接获取文件的LastModifiedBy属性,这是更贴合需求的方式(真正获取最后修改人,而非所有者):

using System.Management;

string filePath = @"C:\Your\File\Path.txt";
string query = $"SELECT LastModifiedBy FROM CIM_DataFile WHERE Name = '{filePath.Replace("\\", "\\\\")}'";

using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
    foreach (ManagementObject obj in searcher.Get())
    {
        string lastModifiedBy = obj["LastModifiedBy"]?.ToString();
        Console.WriteLine($"最后修改人:{lastModifiedBy}");
    }
}

注意:使用WMI需要管理员权限,且文件路径需要转义双反斜杠。

方案3:利用Windows API获取文件信息

通过P/Invoke调用GetFileInformationByHandleEx获取文件的扩展信息,其中包含文件的修改者SID,再进行转换:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Principal;

public static class FileInfoHelper
{
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool GetFileInformationByHandleEx(IntPtr hFile, int infoClass, IntPtr lpBuffer, uint dwBufferSize);

    private const int FileOwnerInfo = 4;

    [StructLayout(LayoutKind.Sequential)]
    private struct FILE_OWNER_INFO
    {
        public IntPtr OwnerSid;
    }

    public static string GetFileLastModifiedBy(string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            FILE_OWNER_INFO ownerInfo = new FILE_OWNER_INFO();
            uint bufferSize = (uint)Marshal.SizeOf(ownerInfo);
            IntPtr buffer = Marshal.AllocHGlobal((int)bufferSize);

            try
            {
                if (GetFileInformationByHandleEx(fs.SafeFileHandle.DangerousGetHandle(), FileOwnerInfo, buffer, bufferSize))
                {
                    ownerInfo = Marshal.PtrToStructure<FILE_OWNER_INFO>(buffer);
                    SecurityIdentifier sid = new SecurityIdentifier(ownerInfo.OwnerSid);
                    try
                    {
                        return sid.Translate(typeof(NTAccount)).Value;
                    }
                    catch (IdentityNotMappedException)
                    {
                        return sid.Value;
                    }
                }
                else
                {
                    throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
    }
}

这个方法底层调用Windows API,兼容性更强,但实现相对复杂。

内容的提问来源于stack exchange,提问作者ejyoung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 07:43:56