如何使用主文件 Table 数据读取文件属性

How to read file attributes using Master File Table data

在我的项目中,我想列出特定文件下的所有文件 path.Do 一些用户权限问题我正在使用主文件 table 访问所有文件。

使用这个thread我可以读取特定文件位置下的所有文件

这个会列出文件名和父FRN,有没有办法也列出文件属性????

我也想展示这些细节。

  1. 创建日期
  2. 修改数据
  3. 文件大小

USN_RECORD 包含这些详细信息。

你可能最好使用更高级别的东西来枚举路径的内容(如@HarryJohnston 所建议的),但如果你决定沿着你选择的路线前进,那么...

使用您从 USN 呼叫中获得的 FileReferenceNumber,您可以呼叫 OpenFileByID (specifying a 0 for the dwDesiredAccess parameter - no read, no write), and you can then subsequently call GetFileInformationByHandle 以获取您需要的详细信息。

您不需要文件的读取或写入权限即可调用 GetFileInformationByHandle。您从 USN 调用 and/or GetFileInformationByHandle 调用中获取的文件属性可以转换为 .Net System.IO.FileAttributes.

public IEnumerable<FileDetails> EnumerateFiles(string szDriveLetter)
        {

            List<FileDetails> fdList = new List<FileDetails>();
            try
            {
                var usnRecord = default(USN_RECORD);
                var mft = default(MFT_ENUM_DATA);
                var dwRetBytes = 0;
                int cb;
                var dicFrnLookup = new Dictionary<long, FSNode>();
                bool bIsFile;

                // This shouldn't be called more than once.
                if (m_Buffer.ToInt32() != 0)
                {
                    throw new Exception("invalid buffer");
                }

                // Assign buffer size
                m_BufferSize = 65536;
                //64KB

                // Allocate a buffer to use for reading records.
                m_Buffer = Marshal.AllocHGlobal(m_BufferSize);

                // correct path
                szDriveLetter = szDriveLetter.TrimEnd('\');

                // Open the volume handle 
                m_hCJ = OpenVolume(szDriveLetter);
                uint iny = NativeMethods.GetLastError();
                // Check if the volume handle is valid.
                if (m_hCJ == INVALID_HANDLE_VALUE)
                {
                    throw new Exception("Couldn't open handle to the volume.");
                }

                mft.StartFileReferenceNumber = 0;
                mft.LowUsn = 0;
                mft.HighUsn = long.MaxValue;

                do
                {
                    if (DeviceIoControl(m_hCJ, FSCTL_ENUM_USN_DATA, ref mft, Marshal.SizeOf(mft), m_Buffer, m_BufferSize, ref dwRetBytes, IntPtr.Zero))
                    {
                        cb = dwRetBytes;
                        // Pointer to the first record
                        IntPtr pUsnRecord = new IntPtr(m_Buffer.ToInt32() + 8);

                        while ((dwRetBytes > 8))
                        {
                            // Copy pointer to USN_RECORD structure.
                            usnRecord = (USN_RECORD)Marshal.PtrToStructure(pUsnRecord, usnRecord.GetType());

                            // The filename within the USN_RECORD.
                            string fileName = Marshal.PtrToStringUni(new IntPtr(pUsnRecord.ToInt32() + usnRecord.FileNameOffset), usnRecord.FileNameLength / 2);

                            bIsFile = !usnRecord.FileAttribute.HasFlag(FileAttributes.Directory);
                            dicFrnLookup.Add(usnRecord.FileReferenceNumber, new FSNode(usnRecord.ParentFileReferenceNumber, fileName, bIsFile));

                            // Pointer to the next record in the buffer.
                            pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnRecord.RecordLength);

                            dwRetBytes -= usnRecord.RecordLength;
                        }

                        // The first 8 bytes is always the start of the next USN.
                        mft.StartFileReferenceNumber = Marshal.ReadInt64(m_Buffer, 0);


                    }
                    else
                    {
                        break; // TODO: might not be correct. Was : Exit Do

                    }

                } while (!(cb <= 8));

                // Resolve all paths for Files
                foreach (FSNode oFSNode in dicFrnLookup.Values.Where(o => o.IsFile))
                {
                    FileDetails fd = new FileDetails();
                    string sFullPath = oFSNode.FileName;
                    FSNode oParentFSNode = oFSNode;

                    while (dicFrnLookup.TryGetValue(oParentFSNode.ParentFRN, out oParentFSNode))
                    {
                        sFullPath = string.Concat(oParentFSNode.FileName, "\", sFullPath);
                    }
                    sFullPath = string.Concat(szDriveLetter, "\", sFullPath);

                    //File Attribute details
                    WIN32_FILE_ATTRIBUTE_DATA data;                

                    if (NativeMethods.GetFileAttributesEx(@sFullPath, GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, out data))
                    {

                        fd.FileSize = Convert.ToDouble(data.fileSizeLow);
                    }

                    long highBits = data.creationTime.dwHighDateTime;
                    highBits = highBits << 32;

                    DateTime createdDate = DateTime.FromFileTimeUtc(highBits + (uint)data.creationTime.dwLowDateTime);
                    fd.CreatedDate = createdDate.ToString(CultureInfo.CurrentCulture);
                    fd.CreatedYear = createdDate.Year;
                    fd.FileType = data.filetype;

                    long highBitsModified = data.lastWriteTime.dwHighDateTime;
                    highBitsModified = highBitsModified << 32;
                    DateTime modifiedDate = DateTime.FromFileTimeUtc(highBitsModified + (uint)data.creationTime.dwLowDateTime);
                    fd.ModifiedYear = modifiedDate.Year;
                    fd.ModifiedDate = modifiedDate.ToString(CultureInfo.CurrentCulture);
                    fd.FilePath = sFullPath;
                    fd.MachineName = SystemInformation.ComputerName;

                    List<string> names = sFullPath.Split('.').ToList();
                    fd.FileType = "." + names.LastOrDefault();                    

                    List<string> folders = sFullPath.Split('\').ToList();
                    //fd.FileName = folders.LastOrDefault();
                    fd.FileName = oFSNode.FileName;
                    fdList.Add(fd);

                    yield return fd;
                }
            }
            finally
            {
                //// cleanup
                Cleanup();
            }
        }

public class NativeMethods
        {
            [DllImport("KERNEL32.dll", CharSet = CharSet.None)]
            public static extern bool GetFileAttributesEx(string path, GET_FILEEX_INFO_LEVELS level, out WIN32_FILE_ATTRIBUTE_DATA data);

            [DllImport("kernel32.dll")]
            public static extern uint GetLastError();

        }