在我的项目中,我希望列出特定文件路径下的所有文件。使用主文件表来访问所有文件,以解决某些用户权限问题。
使用此thread我可以读取特定文件位置下的所有文件
这一个会列出文件名和父FRN,有没有办法列出文件属性呢????
我也想展示这些细节。
答案 0 :(得分:1)
你可能最好使用更高级别的东西来枚举路径的内容(如@HarryJohnston所建议的那样),但是如果你决定沿着这条路走下去,那么你可以选择这样做。然后选择了......
使用您从USN调用获得的FileReferenceNumber,您可以调用OpenFileByID(为dwDesiredAccess参数指定0 - 不读取,不写入),然后您可以随后调用GetFileInformationByHandle来获取你需要的细节。
您不需要对文件具有读取或写入权限即可调用GetFileInformationByHandle。您从USN调用和/或GetFileInformationByHandle调用获取的文件属性可以强制转换为.Net System.IO.FileAttributes。
答案 1 :(得分:0)
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();
}