Windows 参赛作品的数量。与其显示进度条或百分比,不如简单地显示到目前为止已处理的文件/目录的数量?问题:为什么要枚举整个MFT?这可能没有必要。这个答案可能有用:这正是我的理解(或者至少是猜测)。显示计数可能需要做些什么,但我仍然愿意接受任何可能大致接近计数的建议
Windows 参赛作品的数量。与其显示进度条或百分比,不如简单地显示到目前为止已处理的文件/目录的数量?问题:为什么要枚举整个MFT?这可能没有必要。这个答案可能有用:这正是我的理解(或者至少是猜测)。显示计数可能需要做些什么,但我仍然愿意接受任何可能大致接近计数的建议,windows,ntfs,journal,usn,Windows,Ntfs,Journal,Usn,参赛作品的数量。与其显示进度条或百分比,不如简单地显示到目前为止已处理的文件/目录的数量?问题:为什么要枚举整个MFT?这可能没有必要。这个答案可能有用:这正是我的理解(或者至少是猜测)。显示计数可能需要做些什么,但我仍然愿意接受任何可能大致接近计数的建议。您可以使用FSCTL_GET_NTFS_VOLUME_DATA来获取MFT的长度(以字节为单位)。如果将其与选定的代表性卷上的记录数进行比较,则可以估计单个MFT记录的平均长度,并使用此值计算特定卷上记录数的估计值。@HarryJohnsto
参赛作品的数量。与其显示进度条或百分比,不如简单地显示到目前为止已处理的文件/目录的数量?问题:为什么要枚举整个MFT?这可能没有必要。这个答案可能有用:这正是我的理解(或者至少是猜测)。显示计数可能需要做些什么,但我仍然愿意接受任何可能大致接近计数的建议。您可以使用FSCTL_GET_NTFS_VOLUME_DATA来获取MFT的长度(以字节为单位)。如果将其与选定的代表性卷上的记录数进行比较,则可以估计单个MFT记录的平均长度,并使用此值计算特定卷上记录数的估计值。@HarryJohnston-感谢您提供指向其他答案的链接,虽然我认为这基本上证实了我目前的做法。我认为您关于为esimate使用MFT大小的建议很好。嗨,Harry,我做了一些实验,发现了一件有趣的事情-FSCTL_ENUM_USN_DATA实际上返回MFT偏移量作为下一个“StartFileReferenceNumber”或USN(取决于您阅读的MSDN文档的哪个部分!)。该数字相对较小,与FRN或USN无关。因此,我所做的是使用FSCTL_GET_NTFS_VOLUME_数据获取MFT的大小,然后将此MFT pos视为进度指标。在我的系统(Windows 7 SP1)上,FSCTL_ENUM_USN_数据返回的数字肯定是文件引用号。我认为它总是必须的,因为这是你在下一次调用中传递给StartFileReferenceNumber的内容。你在运行什么操作系统?(如果“参考号”实际上是一个偏移量,这是有意义的,但我得到的数字不是,因为它们通常是连续的。)这是我在WinXP SP2上的工作机器。由于它不是记录在案的行为,我可能不应该依赖它,而且我猜它在7上不起作用(我将尝试)。返回的USN记录的FileReferenceNumber字段顺序不正确(尽管它们似乎是近似顺序)。在64位Windows 7上,这对我来说是一样的:FSCTL_ENUM_USN_DATA返回大约0到sizeof(MFT)/1024之间的单调值作为StartFileReferenceNumber。返回的记录数就是系统上的项目数;我无意中从文件参考号中去掉了前四个字节。请参阅我在回答中添加的附加部分。
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct NTFS_EXTENDED_VOLUME_DATA
{
public VOLUME_ID /**/ VolumeSerialNumber;
public long /**/ NumberSectors;
public long /**/ TotalClusters;
public long /**/ FreeClusters;
public long /**/ TotalReserved;
public uint /**/ BytesPerSector;
public uint /**/ BytesPerCluster;
public int /**/ BytesPerFileRecordSegment; // <--
public uint /**/ ClustersPerFileRecordSegment;
public long /**/ MftValidDataLength; // <--
public long /**/ MftStartLcn;
public long /**/ Mft2StartLcn;
public long /**/ MftZoneStart;
public long /**/ MftZoneEnd;
public uint /**/ ByteCount;
public ushort /**/ MajorVersion;
public ushort /**/ MinorVersion;
public uint /**/ BytesPerPhysicalSector;
public ushort /**/ LfsMajorVersion;
public ushort /**/ LfsMinorVersion;
public uint /**/ MaxDeviceTrimExtentCount;
public uint /**/ MaxDeviceTrimByteCount;
public uint /**/ MaxVolumeTrimExtentCount;
public uint /**/ MaxVolumeTrimByteCount;
};
public enum FSCTL : uint
{
// etc... etc...
FILESYSTEM_GET_STATISTICS /**/ = (9 << 16) | 0x0060,
GET_NTFS_VOLUME_DATA /**/ = (9 << 16) | 0x0064, // <--
GET_NTFS_FILE_RECORD /**/ = (9 << 16) | 0x0068,
GET_VOLUME_BITMAP /**/ = (9 << 16) | 0x006f,
GET_RETRIEVAL_POINTERS /**/ = (9 << 16) | 0x0073,
// etc... etc...
ENUM_USN_DATA /**/ = (9 << 16) | 0x00b3,
READ_USN_JOURNAL /**/ = (9 << 16) | 0x00bb,
// etc... etc...
CREATE_USN_JOURNAL /**/ = (9 << 16) | 0x00e7,
// etc... etc...
};
// etc..
if (!GetDeviceIoControl(h_vol, FSCTL.GET_NTFS_VOLUME_DATA, out NTFS_EXTENDED_VOLUME_DATA vd))
throw new Win32Exception(Marshal.GetLastWin32Error());
var c_mft_estimate = (vd.MftValidDataLength + (vd.BytesPerFileRecordSegment - 1))
/ vd.BytesPerFileRecordSegment;
[StructLayout(LayoutKind.Sequential)]
public struct MFT_IX_REC
{
public ushort seq;
public ushort parent_ix_hi;
public uint parent_ix;
};
var med = new MFT_ENUM_DATA { ... };
// ...
var rg_mftix = new MFT_IX_REC[c_mft_estimate];
// ... ready to go, without having to check whether the array needs resizing within the loop
for (int i=0; DeviceIoControl(h_vol, FSCTL.ENUM_USN_DATA, in med, out USN_RECORD usn, ...); i++)
{
// etc..
rg_mftix[i].parent_ix = (uint)usn.ParentId;
// etc..
}